我目前在 python 中的 math.floor() 函数存在一些问题。我正在尝试计算以下值:
math.floor((3710402416420168191+3710402416420167681)/2)
这正在产生答案
3710402416420167680
我知道这是不对的。我认为这与 Python 对非常大的数字进行算术运算的能力有关——任何人都可以帮忙吗?
谢谢!
我目前在 python 中的 math.floor() 函数存在一些问题。我正在尝试计算以下值:
math.floor((3710402416420168191+3710402416420167681)/2)
这正在产生答案
3710402416420167680
我知道这是不对的。我认为这与 Python 对非常大的数字进行算术运算的能力有关——任何人都可以帮忙吗?
谢谢!
我无法在我的机器上重现您的结果:
math.floor((3710402416420168191+3710402416420167681)/2)
正在返回这个,这对于给定的精度是正确的:
3.7104024164201677e+18
当您尝试打印上述结果时,可能会发生错误?这显然失去了一些精度,因为math.floor()
返回一个浮点数,而不是一个整数。
避免使用浮点数。Python 仅对浮点数使用 53 位精度,但整数可以任意增长:
>>> int((3710402416420168191 + 3710402416420167681) / 2)
3710402416420167680
>>> (3710402416420168191 + 3710402416420167681) // 2
3710402416420167936
//
是地板除法,所以它会返回结果的组成部分而不诉诸浮点数(这是math.floor
返回的)。
这两个数字的平均值大于可以用浮点数忠实表示的小数位数:
import sys
print sys.float_info
输出:
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
dig=15
意味着只有 15 个有效数字可以在浮点数中可靠地表示。有关更多信息,请参阅此处的文档。
正如其他人指出的那样,如果您使用整数和地板除法,则没有这样的问题:
(3710402416420168191+3710402416420167681)//2
输出:
3710402416420167936
Python 可以执行任意精度的整数运算,但在表示浮点平均值的有效数字数量方面受到限制。如果这两个数字足够接近,你可能会有更好的运气
x = 3710402416420168191
y = 3710402416420167681
math.floor( x - (x-y)/2.0 )
与它们的总和相比,保持x
和的差异所需的有效数字要少得多。y
更新:仔细观察,问题不在于数学,而在于将生成的大整数转换为浮点数,浮点数不能精确地表示整数。整数结果
(3710402416420168191+3710402416420167681)/2
是正确的,但是将该值传递给math.floor
会导致舍入不佳的值。