是否有可能预测 Perl 的十进制/浮点数数学何时会出错?



在一个方面,我理解Perl的浮点是不精确的二进制表示,这导致Perl的数学有时是错误的。我不明白的是,为什么有时这些漂浮物似乎给出了确切的答案,而其他时候却没有是否可以预测Perl的浮点运算何时会给出错误的答案(即不精确的答案)

例如,在下面的代码中,当减法为"16.12-15.13"时,Perl的数学是错误的1次,当问题为"26.12-25.13"时错的2次,当题为"36.12-35.13"时错的20次。此外,由于某种原因,在上述所有测试案例中,我们的减法问题(即$subtration_eproblem)的结果一开始都是错误的,但我们对它的加减(用$x)越多,它就会变得越正确。这毫无意义,为什么我们在算术问题上加减得越多,这个值就越有可能是正确的(即精确的)?

my $subtraction_problem = 16.12 - 15.13;
my $perl_math_failures = 0;
for (my $x = -25; $x< 25; $x++){
        my $result = $subtraction_problem +$x;
        print "$resultn";
        $perl_math_failures++ if length $result > 6;
}
print "There were $perl_math_failures perl math failures!n";

这些都不是Perl特有的。参见Goldberg:

舍入误差

将无限多个实数压缩成有限数量的位需要近似表示。尽管有无限多的整数,但在大多数程序中,整数计算的结果可以存储在32位中。相反,给定任何固定位数,大多数实数计算都会产生无法使用那么多位数精确表示的量因此,浮点计算的结果必须经常进行四舍五入,以适应其有限表示。这种舍入误差是浮点计算的特征。相对误差和Ulps一节介绍了如何测量相对误差。

既然大多数浮点计算都有舍入误差,那么如果基本算术运算引入的舍入误差比必要的多一点,这有关系吗?这个问题是贯穿本节的一个主要主题。保护数字一节讨论了保护数字,这是一种在减去两个附近数字时减少误差的方法。IBM认为保护数字非常重要,因此在1968年,它在System/360体系结构的双精度格式中添加了一个保护数字(单精度已经有了保护数字),并对该领域的所有现有机器进行了改造。举例说明了保护数字的实用性。

IEEE标准不仅仅要求使用保护数字。它给出了一个加法、减法、乘法、除法和平方根的算法,并要求实现产生与该算法相同的结果。因此,当程序从一台机器移动到另一台机器时,如果两台机器都支持IEEE标准,则基本操作的结果在每一位都是相同的。这大大简化了程序的移植。该精确规范的其他用途在精确舍入运算中给出。

最新更新