我很难理解这一点:
>>> 52920*(15303855351918+15303855298999)/2.0 == 809880023823263820
False
>>> 52920*(15303855351918+15303855298999)/2.0 == 809880023823263820.0
True
>>> (52920*(15303855351918+15303855298999)/2.0) - 809880023823263820
0.0
>>> int(52920*(15303855351918+15303855298999)/2.0)
809880023823263872
>>> int(52920/2.0)*(15303855351918+15303855298999)
809880023823263820
运行Python 3.5.3
数字809880023823263820显然可以表示为整数,因为它是a.p.的总和。包含所有整数参数的系列。第一次和第四次计算的解释是什么?
答案 0 :(得分:2)
Python int
对象具有无限精度(仅受内存限制)。 float
个对象没有无限的精度;数字表示为指数和重要数字,后者用53 二进制分数构建数字。二进制分数不能代表每个可能的十进制数,这就是这里发生的事情。
809880023823263820
无法清晰表示:
>>> float(809880023823263820)
8.098800238232639e+17
>>> format(float(809880023823263820), 'f')
'809880023823263872.000000'
该号码以最后两位数字的形式存储;它们是72
,而不是20
。
请注意,浮点值始终存储为分数,指数确定小数点的位置;有非'整数部分'。非常大和非常小的数字都只是表示为小数点移动了指数的分数。
对于第三个表达式,Python 将数字转换为通用类型。从float中减去一个整数会导致整数首先转换为float。由于float(809880023823263820)
与-
运算符左侧的结果具有相同的浮点值,因此结果为0.0
。
来自表达式参考文档的Binary arithmetic operations section:
-
(减法)运算符产生其参数的差异。数字参数首先转换为通用类型。
和单独的Arithmetic conversions section文档说明了这种转换是如何完成的:
当下面的算术运算符的描述使用短语“数字参数转换为公共类型”时,这意味着内置类型的运算符实现如下:
- 如果任一参数是复数,则另一个参数转换为复数;
- 否则,如果任一参数是浮点数,则另一个转换为浮点数;
- 否则,两者必须是整数,不需要转换。
您可能想要探索有理数的不同的表示,fractions
或decimal
模块。让您将有理数作为抽象分数处理,或者让您配置数字精度。
答案 1 :(得分:2)
浮点数的精度有限,而整数具有任意精度。这意味着你不能在Python中将每个整数表示为float!如果你检查,你可以很容易地看到这个:
>>> 809880023823263820 == 809880023823263820.0
False
>>> 809880023823263820 == int(809880023823263820.0)
False
来自Wikipedia:
53位有效位精度给出15到17个有效十进制数字精度(2-53≈1.11×10-16)。如果具有最多15位有效数字的十进制字符串转换为IEEE 754双精度表示,然后转换回具有相同位数的十进制字符串,则最终结果应与原始字符串匹配。
但是你的整数有18位数,所以你不应该指望一个浮点数可以精确地代表那个整数。有些值可以精确表示,长度超过18位,但条件必须是“正确的”(例如2的幂):
>>> 2.0 ** 80 + 1 == 2 ** 80 + 1
False
>>> 2.0 ** 80 == 2 ** 80
True
你的最后一个例子实际上有点误导,因为52920/2.0
可以完全表示为float,因为你实际上将它转换为一个整数,计算将完全用整数完成,并产生一个准确的整数结果。
在一般情况下,您可以使用Fraction
来准确表示值:
>>> from fractions import Fraction
>>> Fraction(52920*(15303855351918+15303855298999), 2) == 809880023823263820
True
请注意, 2
,而不是此处的/ 2.0
。