我在Perl中有一个简单的for循环
for ($i=0; $i <= 360; $i += 0.01)
{
print "$i ";
}
Run Code Online (Sandbox Code Playgroud)
为什么当我运行这段代码时,我得到以下输出,一旦达到0.81,它突然开始加载更多的小数位?我知道我可以简单地围绕以避免这个问题,但我想知道它为什么会发生.0.01的增量似乎并不疯狂.
0.77
0.78
0.79
0.8
0.81
0.820000000000001
0.830000000000001
0.840000000000001
0.850000000000001
0.860000000000001
0.870000000000001
Run Code Online (Sandbox Code Playgroud)
Jen*_*rat 16
计算机使用二进制表示.并非所有十进制浮点数都具有二进制表示法的精确表示,因此可能会发生一些错误(实际上是一个舍入差异).这与您不应将浮点数用于货币值的原因相同:
弄乱了收件人http://img.thedailywtf.com/images/200902/errord/DSC00669.JPG
(图片来自dailywtf)
解决此问题的最优雅方法是使用整数进行计算,将它们分成正确的小数位数并使用sprintf限制打印的小数位数.这将确保:
试试这段代码:
#!/usr/bin/perl
for ($i=0; $i <= 360*100; $i += 1) {
printf "%.2f \n", $i/100;
}
Run Code Online (Sandbox Code Playgroud)
基本上,因为十进制数0.01在二进制浮点中没有精确表示,所以随着时间的推移,将最佳近似值加到0.01会偏离您想要的答案.
这是(二进制)浮点运算的基本属性,而不是Perl特有的.每个计算机科学家应该知道的关于浮点算术是标准参考,你可以通过谷歌搜索很容易地找到它.
另请参阅:C编译器错误(浮点运算),毫无疑问是无数其他问题.
Kernighan&Plauger在他们古老但经典的书"编程风格的元素"中说:
他们还说:
两种说法都指出浮点运算不精确.
请注意,一些现代CPU(IBM PowerPC)内置了IEEE 754:2008十进制浮点运算.如果Perl使用了正确的类型(可能没有),那么你的计算就是精确的.
| 归档时间: |
|
| 查看次数: |
662 次 |
| 最近记录: |