是否在perl中排序时浮点数发生了变化?

时间:2016-03-07 20:28:23

标签: arrays perl sorting floating-point

我正在运行10k排列的统计引导程序,我试图将其与观察值进行比较。观察到的应该与10k排列的最大值相同。我衡量这一点的方法是试图找到它的百分位数。

10k排列的所有结果(10,000个随机数)存储在一个数组中,我使用它排序:

$truevalue

当我比较观察值if ($sorted[$#sorted] == $truevalue) { print "sorted: $sorted[$#sorted] is eq truevalue:$truevalue\n"; } elsif ($sorted[$#sorted] > $truevalue) { print "sorted: $sorted[$#sorted] is gt truevalue:$truevalue\n"; } elsif ($sorted[$#sorted] < $truevalue) { print "sorted: $sorted[$#sorted] is lt truevalue:$truevalue, totalpermvalues; $totalpermvalues\n"; } 时,我得到的结果不准确。它们存储为浮点数。引导过程使用相同的公式生成随机数,因此它应该完全相同,但是当比较相同的值时,它变得不准确。我正在测试这个:

sorted: 0.937864522389543 is gt truevalue:0.937864522389543

输出:

@document_history

所以我得到浮点数不能完全准确地打印,但我总是在内部假设计算机存储正确的数字。这不是一个正确的假设吗?当然我可以通过将它们变成某种整数来快速解决这个问题,但这是我应该一直自动完成的事情吗?浮点数是否危险?那些确切的值应该是相同的,因为它们是相同输入的输出,这让我感到困惑......

如果这很重要,则使用Math :: Interpolate包中的linear_interpolate函数单独计算值,但输入相同。

2 个答案:

答案 0 :(得分:4)

如果我理解正确,您会想知道为什么==返回false并且>对于看起来相同的数字而返回true。显然,这些数字实际上并不相同。你可以通过打印更多数字来看到这一点。

printf "sorted: %.80e is gt truevalue:%.80e\n", $sorted[$#sorted], $truevalue;

答案 1 :(得分:3)

不,排序不会改变值。必须假设 这两个值的生成方式存在差异。

当然可以将==与浮点数(FPN)一起使用,如果一对64位数量相同,则返回true。但是当人们问“这两个FPN是否相等?”时,必须非常小心。

在FPN中可以准确地表示(相对较小但仍然相当)的整数和有理数。对于这些(并且仅针对这些),诸如“FPN a 等于到1.5?”之类的问题。 (写作$a==1.5可能 - 不要掉以轻心:以下两个陈述是否都会打印“1”?

print 0.12345678901234567 == 1.2345678901234567E-1,"\n";
print 0.12345678901234567 == 12.345678901234567E-2,"\n";

所有FPN不仅代表它们准确表示的值 x 。它们还负责实数的区间,包括比 x “更大,更小”的理性,非理性和超越(甚至整数)数字。你可以量化“一点点”:对于x == 1.0,它是1e-16,并相应地缩小或增长。因此,例如,1 + 1e-17将在您的计算机上为1.0。您可以输入此数字,但FPN将为1.0。询问FPN作为某些计算的结果是否等于1 + 1e-17是没有意义的,因为你甚至无法告诉计算机这个值。

解决方案并不困难。而不是要求相等,你必须在x周围的区间[ p q ]中询问“FPN a 吗?”应该稍微考虑确定 p q ,因为这些值的合适选择主要取决于 x 。通常的公式类似于

abs( $a - $expect ) <= $expect*PRECISION

其中PRECISION可以是,例如,1e-12。 (此处使用的值可能取决于您用于计算$a的算法,或您的需求,或两者兼而有之。)

最后:由于FP机器指令的数学特性,不保证通常的相关性或分布性的算术规律。加法或减法中的截断效应可能例如导致结果中的严重失真。一个典型的例子来说明这一点,计算一些泰勒级数:一旦按递减顺序添加术语直到术语变得小于给定的限制,一次,使用相同的术语,但按递增的顺序。