jfs Asked:2020-11-22 22:06:27 +0800 CST2020-11-22 22:06:27 +0800 CST 2020-11-22 22:06:27 +0800 CST Python 中的错误:x + 1.0 < x 772 混合类型时,可能会出现不明显的行为: >>> x = (1 << 53) + 1 >>> x + 1.0 < x True 似乎x + 1.0没有少是公正x的,所以比较的预期结果False是,但是被返回True。为什么? python 1 个回答 Voted Best Answer jfs 2020-11-22T22:06:27+08:002020-11-22T22:06:27+08:00 简而言之: 9007199254740992.0 < 9007199254740993 添加时,数字被转换为 Python 中的常见类型。x(int) 转换为浮点数,因为它1.0是浮点数。x不能完全表示为浮点数,因此选择最接近(此处较小)的可表示数字:x -> float(x-1)。因此,总和是不准确的: x+1.0 -> float(x-1)+1.0 -> (x) -> float(x-1) float < int 比较恰好发生。( xint) 值在数学上大于x+1.0(float)。 Python 中的整数具有无限精度(可以任意大)。但是实数,例如由1.0源代码中的常量创建的实数,由 typefloat浮点数表示。 x这个词在这里变成了一个浮点数: 否则,如果任一参数是浮点数,则将另一个转换为浮点数; 在计算总和之前: 将数字转换为通用类型,然后相加 >>> x 9007199254740993 >>> float(x) == float(x-1) == 9007199254740992.0 True >>> x+1.0 == float(x) + 1 == float(x-1) + 1 == float(x) == float(x-1) True 在 IEEE 754 平台上,Python 浮点数对应于双精度数: >>> sys.float_info.radix 2 >>> sys.float_info.mant_dig 53 >>> float(1<<53).hex() # точно представлено '0x1.0000000000000p+53' >>> float((1<<53) + 1).hex() # непредставимо точно, округляется '0x1.0000000000000p+53' >>> (float((1<<53) + 1) + 1.0).hex() # двойное округление '0x1.0000000000000p+53' 输出显示float(x)和x + 1.0表示为相同的数字:float(x-1)。有关详细信息,请参阅问题显示数字 9223372036854775807。 x是int,因此该值(1<<53)+1完全由 (9007199254740993) 表示。 比较在数学上是精确的,没有强制转换: 对象不需要具有相同的类型。 ... 在所涉及类型的限制内,它们在数学上(算法上)比较正确而不会损失精度。 >>> 9007199254740992.0 < 9007199254740993 True 这就是在 Python 中它x + 1.0可以减少的原因。x
简而言之: 9007199254740992.0 < 9007199254740993
添加时,数字被转换为 Python 中的常见类型。
x
(int) 转换为浮点数,因为它1.0
是浮点数。x
不能完全表示为浮点数,因此选择最接近(此处较小)的可表示数字:x -> float(x-1)。因此,总和是不准确的:float < int 比较恰好发生。(
x
int) 值在数学上大于x+1.0
(float)。Python 中的整数具有无限精度(可以任意大)。但是实数,例如由
1.0
源代码中的常量创建的实数,由 typefloat
浮点数表示。x
这个词在这里变成了一个浮点数:在计算总和之前:
在 IEEE 754 平台上,Python 浮点数对应于双精度数:
输出显示
float(x)
和x + 1.0
表示为相同的数字:float(x-1)
。有关详细信息,请参阅问题显示数字 9223372036854775807。x
是int
,因此该值(1<<53)+1
完全由 (9007199254740993) 表示。比较在数学上是精确的,没有强制转换:
这就是在 Python 中它
x + 1.0
可以减少的原因。x