3

我正在研究数学程序,我对回合有一个很大的问题。因此,在我的程序进行了一些数学运算之后,它会对结果进行四舍五入。

一切正常,但如果result == 2.49999999999999992 , round 函数返回3.0而不是2.0.

我该如何解决?

谢谢。

4

2 回答 2

5

正如@Pavel Anossov 在他的评论中所说there's no such thing as 2.49999999999999992 in IEEE 754, 2.49999999999999992 == 2.5.。浮点数可能总是对您的计算至关重要,因为在任何情况下(32/64/128 位浮点数),您都有精度限制。这显然也受限于 Python 浮点数。

有不同的选项可以解决这个问题,例如,您可以使用十进制库:

>>> from decimal import *
>>> getcontext().prec = 6
>>> Decimal(1) / Decimal(7)
Decimal('0.142857')
>>> getcontext().prec = 28
>>> Decimal(1) / Decimal(7)
Decimal('0.1428571428571428571428571429')

在这种情况下,可以自己设置精度。十进制在标准库中。

还有第三方库,例如bigfloat,您可以使用(我没有经验):

>>> from bigfloat import *
>>> sqrt(2, precision(100))  # compute sqrt(2) with 100 bits of precision

但正如您所见,您始终必须选择精度。如果您真的不想失去任何精度,请使用分数(也在标准库中):

>>> from fractions import Fraction
>>> a = Fraction(16, -10)
>>> a
Fraction(-8, 5)
>>> a / 23
Fraction(-8, 115)
>>> float(a/23)
-0.06956521739130435
于 2013-08-11T17:13:49.447 回答
2

原因是 Python 的float类型(通常是 IEEE 754 双精度浮点数)没有 2.49999999999999992 这样的值。浮点数通常在表格mantissa*base**exponent中,在 Python 中,您可以找到float特别是 within的限制sys.float_info。首先,让我们计算尾数本身可以容纳多少位数:

>>> from sys import float_info
>>> print float_info.radix**float_info.mant_dig  # How big can the mantissa get?
9007199254740992
>>> print "2.49999999999999992"
2.49999999999999992
>>> 2.49999999999999992
2.5

显然,我们输入的数字更大。在事情出错之前,我们能走多远?

>>> print 2.5*float_info.epsilon
5.55111512313e-16

e-16这里的意思是*10**-16,所以让我们重新格式化它以进行比较:

>>> print "%.17f"%(2.5*float_info.epsilon); print "2.49999999999999992"
0.00000000000000056
2.49999999999999992

这表明在 2.5 左右的幅度上,低于约 5.6e-16(包括这个 8e-17)的差异将丢失给存储本身。因此,该值为 2.5,四舍五入。

我们还可以计算出我们可以使用多少有效数字的估计值:

>>> import math, sys
>>> print math.log10(sys.float_info.radix**sys.float_info.mant_dig)
15.9545897702

非常接近,但不完全是 16。在二进制中,第一个数字将始终为 1,因此我们可以有已知数量的有效数字(mant_dig),但在十进制中,第一个数字将消耗 1 到 4 位。这意味着最后一位数字可能相差一个以上。通常我们通过仅以有限的精度打印来隐藏它,但它实际上发生在很多数字上:

>>> print '%f = %.17f'%(1.1, 1.1)
1.100000 = 1.10000000000000009
>>> print '%f = %.17f'%(10.1, 10.1)
10.100000 = 10.09999999999999964

这就是浮点数固有的不精确性。bigfloat,decimal和(感谢 David Halter 提供这些示例)之类的类型fractions可以突破限制,但是如果您开始查看许多数字,则需要注意它们。另请注意,这不是计算机独有的;一个无理数,例如 pi 或 sqrt(2),不能精确地写成任何整数基数。

于 2013-10-01T13:11:41.177 回答