True
?a = 2/3
b = 4/6
print(a == b)
我有一个算法,需要对一个数字列表进行排序,其中每个数字都是x/y形式的,其中x和y是整数。(y != 0)。
我担心除法的数值精度会导致不稳定性和任意排序,例如上面的情况。这是相关评论的一个例子。但是,根据这个例子和更大的整数,似乎这不是一个问题。
Python是否从b的分子和分母中删除2的公共因素,并保留a和b不仅仅是浮点数的信息?
True
?a = 2/3
b = 4/6
print(a == b)
Python遵循IEEE 754浮点数规范。* (64位)IEEE浮点数本质上是一种基于科学计数法的形式,如下所示:
将浮点数值乘以二或任何二的幂,只会影响指数,而不影响尾数。** 因此,它通常本身是一个相当“稳定”的操作,因此2/3应该产生与4/6相同的结果。 然而,IEEE浮点数仍然存在以下问题:
(a * b) * c != a * (b * c)
)。您应该准备好处理这些问题,并假设大多数数学上等价的浮点表达式将不会产生相同的值。在 Python 中,您可以使用 math.isclose()
来估计两个浮点数是否“足够接近”,以便“可能是相同的值”。
* 实际上,这是一个谎言。 Python 遵循 C 的 double
,通常以某种方式遵循 IEEE 754,但在足够奇特的架构上可能会偏离它。在这种情况下,C 标准提供了很少或没有保证,因此您将不得不查看您的架构或编译器的浮点文档。
** 假设指数不会溢出或下溢。如果发生这种情况,则通常会落在适当签名的无穷大或零上,或者根据架构和/或 Python 编译方式下溢到一个denormal number。
*** “更复杂”的操作的确切集合有所不同,因为 IEEE 754 使许多操作变成可选项,同时要求精度。结果,很少明显是否给定操作符符合 IEEE 754 还是仅符合声名疏于 C 标准的规范。在某些情况下,操作可能根本不符合任何标准。
请注意,只要整数x
和y
在Python浮点数中精确表示,x / y
就是无限精确商的正确舍入值,在所有当前的机器上都是如此。这是IEEE 754浮点标准所要求的,并且所有当前的机器都支持。
因此,在您具体的示例中,重要的部分不是b = 4/6
中的分子和分母有一个(特定!)公因数2,而是(a)它们有一些共同的因数; 和(b) 4和6都可以精确地表示为Python浮点数。
因此,例如,保证
(2 * 9892837) / (3 * 9892837) == 2 / 3
同样适用于这种情况。因为(2 * 9892837) / (3 * 9892837)
的无限精确值与2/3
的无限精确值相同,而IEEE 754除法会像计算出无限精确商一样进行计算。只要这些乘积在Python浮点数中保持完全可表示,就可以将9892837替换为任何其他非零整数。
(n*x)/(n*y) == x/y
对于任意使得n*y
不为0的整数而言都是成立的,并且n*x
和n*y
都可以精确表示为Python浮点数。 - Tim Peters2/3 等同于 4/6。 (2/3)*(2/2) = 2/2 = 1,这是恒等元素。回答正确。