Python 为什么9007199254740993!=9007199254740993.0?

Python 为什么9007199254740993!=9007199254740993.0?,python,floating-point,numbers,comparison-operators,Python,Floating Point,Numbers,Comparison Operators,这个比较的结果令我惊讶(CPython 3.4): 我对的理解是,左操作数应强制转换为float,以匹配右操作数的类型: Python完全支持混合算术:当二进制算术运算符具有不同数值类型的操作数时,具有“窄”类型的操作数将扩展为另一种类型的操作数,其中整数比浮点窄,浮点比复数窄。混合类型的数字之间的比较使用相同的规则。构造函数int()、float()和complex()可用于生成特定类型的数字 这似乎没有发生: >>> float(9007199254740993) == 9

这个比较的结果令我惊讶(CPython 3.4):

我对的理解是,左操作数应强制转换为
float
,以匹配右操作数的类型:

Python完全支持混合算术:当二进制算术运算符具有不同数值类型的操作数时,具有“窄”类型的操作数将扩展为另一种类型的操作数,其中整数比浮点窄,浮点比复数窄。混合类型的数字之间的比较使用相同的规则。构造函数int()、float()和complex()可用于生成特定类型的数字

这似乎没有发生:

>>> float(9007199254740993) == 9007199254740993.0
True
这里发生了什么?

Python并没有将整数精确地转换为浮点;它将浮点转换为整数:

>>> 9007199254740993 == int(9007199254740993.0)
False
这会失败,因为int(9007199254740993.0)实际上是9007199254740992:

>>> 9007199254740992 == 9007199254740993.0
True
看。具体而言,面前的评论:

比较简直是一场噩梦。 [...] *当混合浮点和整数类型时,没有好的“统一”方法。 *将double转换为整数显然不起作用,因为我们 *可能会丢失分数位的信息。将整数转换为双精度 *也有两种故障模式:(1)int可能会触发溢出(太多) *大到适合C双精度的动态范围);(2) 即使是C长也可能有 *C-double(例如,在64位的长方体上,可能有超过合适的位) *63位精度,但C双精度可能只有53位),然后 *当低阶整数位丢失时,我们可以错误地声明相等 *强迫加倍。所以这部分也很痛苦。 这两个数字的结果是:

  • Python尝试
    int.\uuuuueq\uuuuuu(float)
    路由,但返回
    NotImplemented
  • Python尝试
    float.\uuuueq\uuuint(int)
    route,由
    float\urichcompare()处理
在该函数中,
v
是浮点,
w
是整数。以下是为该路径执行的代码选择:

else if(PyLong_Check(w)){/*true,因为另一个数字是Python整数*/
/* ... */
nbits=_PyLong_NumBits(w);/*54表示整数*/
/* ... */

如果(注意,
9007199254740993.0
实际上是
9007199254740992.0
。根据丹的回答,你可以通过检查
(9007199254740993-9007199254740993.0)==0.0
(因为
-
无疑是一个算术运算符)来测试是否相等.至于原因,请看,在学校里,我被教导永远不要与浮点进行精确比较。相反,允许一个微小的错误,并使用>=和@mehtunguh注意,在这种情况下,这是相同的规则-两者都应转换为
浮点
>>> 9007199254740992 == 9007199254740993.0
True
>>> 9007199254740993.0
9007199254740992.0