Viv*_*tya 2 c floating-point floating-point-precision
当我使用float而不是使用奇怪的输出double
#include <stdio.h>
void main()
{
double p,p1,cost,cost1=30;
for (p = 0.1; p < 10;p=p+0.1)
{
cost = 30-6*p+p*p;
if (cost<cost1)
{
cost1=cost;
p1=p;
}
else
{
break;
}
printf("%lf\t%lf\n",p,cost);
}
printf("%lf\t%lf\n",p1,cost1);
}
Run Code Online (Sandbox Code Playgroud)

按预期输出p= 3;
但是当我使用float输出时有点奇怪.
#include <stdio.h>
void main()
{
float p,p1,cost,cost1=40;
for (p = 0.1; p < 10;p=p+0.1)
{
cost = 30-6*p+p*p;
if (cost<cost1)
{
cost1=cost;
p1=p;
}
else
{
break;
}
printf("%f\t%f\n",p,cost);
}
printf("%f\t%f\n",p1,cost1);
}
Run Code Online (Sandbox Code Playgroud)

为什么p第二种情况下的增量在2.7之后变得奇怪?
yel*_*hil 11
发生这种情况是因为float和double数据类型在基数2中存储数字.大多数基数为10的数字无法准确存储.使用floats 时,舍入错误加起来要快得多.在内存有限的嵌入式应用程序之外,double由于这个原因,使用s 通常会更好,或者至少更容易.
要查看double类型的发生情况,请考虑此代码的输出:
#include <stdio.h>
int main(void)
{
double d = 0.0;
for (int i = 0; i < 100000000; i++)
d += 0.1;
printf("%f\n", d);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的电脑上,它输出9999999.981129.因此,经过1亿次迭代后,舍入误差在结果中产生了0.018871的差异.
有关浮点数据类型如何工作的更多信息,请阅读每个计算机科学家应该知道的关于浮点运算的内容.或者,正如评论中提到的akira,请参阅浮点指南.
你的程序可以很好地工作float.您不需要double将包含100个值的表格计算为几位有效数字.你可以使用double,如果你这样做,即使你在交叉目的使用二进制浮点二进制文件,它也有机会工作.double大多数C编译器使用的IEEE 754双精度格式是如此精确,以至于它使得浮点的许多误用都不明显(但不是全部).
结果是十进制简单的值可能无法用二进制表示.
这是0.1的情况:二进制并不简单,并且它没有完全表示为double或者float,但是double表示具有更多数字,因此更接近预期值1/10.
以诸如float或double必须以预期格式产生结果的格式的二进制浮点运算.这导致每次计算操作时必须从结果中删除一些数字.当以高级方式使用二进制浮点时,程序员有时会知道结果将具有足够的数字,以便以格式表示所有数字(换句话说,有时浮点运算可以是精确的和高级程序员可以预测并利用发生这种情况的条件).但是在这里,你要添加0.1,这不简单,并且(二进制)使用所有可用的数字,所以大多数时候,这个添加并不准确.
在for (p = 0.1; p < 10;p=p+0.1),每个迭代将舍入p作为a 的值float.每次迭代将从已经舍入的先前迭代计算,因此舍入误差将累积并使最终结果偏离预期的数学值.
以下是与您所写内容相比的改进列表,与正确性的顺序相反:
for (i = 1, p = 0.1f; i < 100; i++, p = i * 0.1f)
Run Code Online (Sandbox Code Playgroud)
在上面的版本中,0.1f不完全是1/10,但计算p只涉及一次乘法和一次舍入,而不是最多100次.该版本给出了i/10的更精确的近似值.
for (i = 1, p = 0.1f; i < 100; i++, p = i * 0.1)
Run Code Online (Sandbox Code Playgroud)
在上面稍微不同的版本中,i乘以该double值0.1,该值更接近1/10.结果总是最接近floati/10,但这个解决方案有点作弊,因为它使用double乘法.我说只有一个解决方案存在float!
for (i = 1, p = 0.1f; i < 100; i++, p = i / 10.0f)
Run Code Online (Sandbox Code Playgroud)
在最后一个解决方案中,p计算为除法i,完全表示为a float因为它是一个小整数,由于10.0f同样的原因也是精确的.唯一的计算近似值是单个操作,并且参数正是我们想要的,所以这是最好的解决方案.float对于1到99之间的所有i值,它产生最接近i/10的值.
| 归档时间: |
|
| 查看次数: |
247 次 |
| 最近记录: |