我正在将一个MATLAB代码移植到Python 3.5.1中,我发现了一个浮动舍入问题。
在MATLAB中,以下数字将向上四舍五入到小数点后第六位:
fprintf(1,'%f', -67.6640625);
-67.664063
另一方面,在Python中,以下数字将关闭舍入到第6个小数位:
print('%f' % -67.6640625)
-67.664062
有趣的是,如果数字是'-67.6000625',那么即使在Python中,它也会被向上四舍五入:
print('%f' % -67.6000625)
-67.600063
......为什么会这样? 在Python中舍入/增加的标准是什么? (我认为这与处理十六进制值有关。)
更重要的是,我该如何防止这种差异? 我应该创建一个python代码,它可以重现与MATLAB生成完全相同的输出。
答案 0 :(得分:4)
python行为的原因与浮点数如何存储在计算机中以及IEEE定义的标准化舍入规则有关,它定义了几乎所有现代计算机上使用的标准数字格式和数学运算。
需要在计算机上以二进制形式有效地存储数字,这导致计算机使用浮点数。这些数字很容易让处理器使用,但缺点是许多十进制数cannot be exactly represented。这导致数字有时与我们认为的数字相差无几。
如果我们在Python中扩展值而不是截断它们,情况会变得更清楚:
>>> print('%.20f' % -67.6640625)
-67.66406250000000000000
>>> print('%.20f' % -67.6000625)
-67.60006250000000704858
正如您所看到的,-67.6640625
是一个可以准确表示的数字,但-67.6000625
不是,它实际上要大一些。浮点数的默认舍入模式defined by the IEEE stanard表示高于5
的任何内容都应向上舍入,下面的任何内容都应向下舍入。因此对于-67.6000625
的情况,它实际上是5
加上一小部分,所以它被四舍五入。但是,在-67.6640625
的情况下,它恰好等于五,所以一个抢七规则发挥作用。默认的仲裁规则是舍入到最接近的偶数。由于2
是最近的事件编号,因此它会向下舍入为两个。
因此Python遵循浮点标准推荐的方法。那么问题就是你的MATLAB 版本没有这样做的原因。我用64位MATLAB R2016a在我的计算机上试过它,得到了与Python相同的结果:
>> fprintf(1,'%f', -67.6640625)
-67.664062>>
因此,似乎MATLAB在某种程度上使用了不同的舍入方法(可能是非标准方法,也许是标准中指定的替代方法之一),并且已经切换到遵循与其他人相同的规则