简体   繁体   English

Python等于浮点除法

[英]Python equality of floating point divisions

Using Python 3, how does the following return True ? 使用Python 3,以下内容如何返回True

a = 2/3
b = 4/6
print(a == b)

I have an algorithm that requires sorting a list of numbers which are each of the form x/y where x and y are integers. 我有一个算法,需要排序一个数字列表,每个数字的形式为x / y,其中x和y是整数。 (y != 0). (y!= 0)。

I was concerned that the numerical precision of the division would result in instability and arbitrary ordering of cases such as above. 我担心分裂的数值精度会导致上述情况的不稳定性和任意排序。 This being an example of relevant comments. 这是相关评论的一个例子。 But, as per the example and for larger integers as well, it does not seem to be an issue. 但是,根据示例和更大的整数,它似乎不是一个问题。

Does Python remove the common factor of 2 from the numerator and denominator of b, and retain information that a and b are not just floats? Python是否从b的分子和分母中删除了公因子2,并保留a和b不仅仅是浮点数的信息?

Python follows the IEEE 754 floating point specification.* (64-bit) IEEE floats are essentially a form of base 2 scientific notation , broken down as follows: Python遵循IEEE 754浮点规范。*(64位)IEEE浮点数基本上是基础2 科学记数法的一种形式,细分如下:

  • One bit for the sign (positive or negative) 符号一位(正面或负面)
  • 53 bits for the mantissa or significand, including the implied leading one. 尾数或有效数的53位,包括隐含的前导。
  • 11 bits for the exponent. 指数为11位。

Multiplying or dividing a floating point value by two, or any power of two, only affects the exponent, and not the mantissa.** As a result, it is normally a fairly "stable" operation by itself, so 2/3 should yield the same result as 4/6. 将浮点值乘以或除以2,或任何2的幂,只影响指数,而不影响尾数。**因此,它通常是一个相当“稳定”的运算,所以2/3应该产生与4/6相同的结果。 However, IEEE floats still have the following problems: 但是,IEEE浮动仍然存在以下问题:

  • Most operations are not associative (eg (a * b) * c != a * (b * c) in the general case). 大多数操作不是关联的(例如,在一般情况下(a * b) * c != a * (b * c) )。
  • More complicated operations are not required to be correctly rounded (however, as Tim Peters points out, division certainly is not a "more complicated" operation and will be correctly rounded).*** 更复杂的操作不需要正确舍入(但是,正如蒂姆·彼得斯指出的那样,除法当然不是“更复杂”的操作并且将被正确舍入)。***
  • Intermediate results are always rounded to 53 bits. 中间结果总是四舍五入为53位。

You should be prepared to handle these issues and assume that most mathematically-equivalent floating point expressions will not result in identical values. 您应该准备好处理这些问题并假设大多数在数​​学上等效的浮点表达式不会产生相同的值。 In Python specifically, you can use math.isclose() to estimate whether two floats are "close enough" to be "probably the same value." 特别是在Python中,您可以使用math.isclose()来估计两个浮点数是否“足够接近”以“可能是相同的值”。


* Actually, this is a lie. *实际上,这是一个谎言。 Python follows C's double , which nearly always follows IEEE 754 in some fashion, but might deviate from it on sufficiently exotic architectures. Python遵循C的double ,它几乎总是以某种方式遵循IEEE 754,但在充分奇特的架构上可能会偏离它。 In such cases the C standard provides few or no guarantees, so you will have to look to your architecture or compiler's floating point documentation. 在这种情况下,C标准提供很少或没有保证,因此您必须查看您的体系结构或编译器的浮点文档。

** Provided the exponent does not overflow or underflow. **如果指数不上溢或下溢。 If it does, then you will typically land on an appropriately-signed infinity or zero, respectively, or you might underflow to a denormal number depending on architecture and/or how Python was compiled. 如果确实如此,那么通常会分别使用适当签名的无穷大或零,或者根据体系结构和/或Python的编译方式,您可能会下降到非正规数

*** The exact set of "more complicated" operations varies somewhat because IEEE 754 made a lot of operations optional while still demanding precision . ***确切的“更复杂”操作集有所不同,因为IEEE 754 使得许多操作可选,同时仍然要求精确度 As a result, it is seldom obvious whether a given operation conforms to IEEE 754 or only conforms to the notoriously lax C standard. 结果,给定的操作是符合IEEE 754还是仅符合众所周知的宽松C标准很少是显而易见的。 In some cases, an operation may conform to no standard whatsoever. 在某些情况下,操作可能不符合任何标准。

Just noting that so long as integers x and y are exactly representable as Python floats, x / y is - on all current machines - the correctly rounded value of the infinitely precise quotient. 只要注意,只要整数xy完全可以表示为Python浮点数, x / y就是 - 在所有当前机器上 - 无限精确商的正确舍入值。 That's what the IEEE 754 floating-point standard requires, and all current machines support that. 这就是IEEE 754浮点标准所要求的,而且所有当前的机器都支持这一点。

So the important part in your specific example isn't that the numerator and denominator in b = 4/6 have a factor of (specifically!) 2 in common, it's that (a) they have some factor in common; 因此,在你的具体例子中,重要的部分并不是b = 4/6中的分子和分母具有(特别是!)2的共同因子,它是(a)它们有一些共同的因素; and, (b) 4 and 6 are both exactly representable as Python floats. 并且,(b)4和6都可以完全代表Python浮点数。

So, for example, it's guaranteed that 所以,例如,它保证了

(2 * 9892837) / (3 * 9892837) == 2 / 3

is also true. 也是如此。 Because the infinitely precise value of (2 * 9892837) / (3 * 9892837) is the same as the infinitely precisely value of 2/3 , and IEEE 754 division acts as if the infinitely precise quotient were computed. 因为(2 * 9892837) / (3 * 9892837)的无限精确值与2/3的无限精确值相同,并且IEEE 754除法就好像计算了无限精确的商。 And you can replace 9892837 with any other non-zero integer in that, provided that the products remain exactly representable as Python floats. 并且您可以将9892837替换为其中的任何其他非零整数,前提是产品仍然可以像Python浮点数那样完全表示。

2/3 is the same as 4/6. 2/3与4/6相同。 (2/3)*(2/2) = 2/2 = 1, the identity element. (2/3)*(2/2)= 2/2 = 1,标识元素。 The response is correct. 回答是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM