为什么App Engine与我的本地机器相比显示不同的浮动舍入结果?

时间:2013-01-28 12:16:30

标签: python google-app-engine

如果您将以下内容放入App Engine Shell,则会获得'50.49'。这个结果在2.5和2.7运行时都是一致的。

 >> a = '%0.2f' % (round(float(u'50.485'), 2),)
 >> a
'50.49'

但是,如果我将相同的东西放入运行python 2.7.1的本地MacBook Pro中,我会得到'50.48'

 >> a = '%0.2f' % (round(float(u'50.485'), 2),)
 >> a
'50.48'

为什么会有所不同,如何在本地计算机和App Engine的服务器之间保持一致?

3 个答案:

答案 0 :(得分:4)

显然,Google App Engine使用“float”C类型(IEEE 754单精度),而本地Python使用“double”代替(IEEE 754双精度)。

我怀疑CPython有一个配置开关使用'float'而不是'double',但是没有找到。

答案 1 :(得分:2)

有趣的是,这个确切的主题在官方Python教程中有所介绍。

浮点算术:问题和限制
http://docs.python.org/2/tutorial/floatingpoint.html

  

其他惊喜也来自这个。例如,如果您尝试舍入   值2.675到两位小数,你得到这个

>>>
>>> round(2.675, 2)
2.67
     

内置round()函数的文档说明了它   舍入到最接近的值,从零开始四舍五入。自从   小数分数2.675正好在2.67和2.68之间,你   可能期望这里的结果是(二进制近似)2.68。   它不是,因为当十进制字符串2.675转换为a时   二进制浮点数,它再次被二进制替换   近似,其精确值为

2.67499999999999982236431605997495353221893310546875
     

由于这个近似值略微接近2.67而不是2.68,因此   四舍五入。

     

如果你处在一个你关心小数点的情况   中途案例是四舍五入的,你应该考虑使用小数   模块。顺便提一下,十进制模块也提供了一个很好的方法   “看到”存储在任何特定Python float中的确切值

>>>
>>> from decimal import Decimal
>>> Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')

尽管使用FORTRAN,但官方Python教程(http://www.lahey.com/float.htm)中链接的文章之一正确地描述了IEEE 754的真正含义:

  

不同的计算机使用不同的位数来存储   浮点数字。 即使使用相同的IEEE格式   存储数字,因为计算的差异可能会发生   中间寄存器的大小。增加可移植性并确保   一致的结果,我建议不要比较确切的平等   FORTRAN中的实数。

因此,如果你真的关心这一点,那么一定要使用内置的十进制模块(或者cdecimal模块,这里有http://pypi.python.org/pypi/cdecimal/2.3,如果性能有问题的话)。

答案 2 :(得分:0)

其他答案是正确的,所以我不会就round函数的行为发表任何意见,但如果你想获得一致的结果,可以跳过round,因为你正在使用您在示例中显示的字符串格式('%0.2f')。

>> a = '%0.2f' % (float(u'50.485'))
>> a
'50.48'