Why is a**2 != a * a for some floats?

  • A+
$ python --version Python 2.7.15  $ type test.py import random  while True:     a = random.uniform(0, 1)     b = a ** 2     c = a * a     if b != c:         print "a = {}".format(a)         print "a ** 2 = {}".format(b)         print "a * a = {}".format(c)         break  $ python test.py a = 0.145376687586 a ** 2 = 0.0211343812936 a * a = 0.0211343812936 

I was only able to reproduce this on a Windows build of python - to be precise: Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32. On my arch linux box installation of python (Python 2.7.15 (default, May 1 2018, 20:16:04) [GCC 7.3.1 20180406] on linux2) the loop does not seem to terminate indicating that the a**2 = a * a invariant holds there.

What is going on here? I know that IEEE floats come with a plethora of misconceptions and idiosyncrasies (this for example does not answer my question) but I fail to see what part of the spec or what kind of implementation of ** could possibly allow for this.

Edit: To address the duplicate flagging: This is most likely not directly a IEEE floating point math problem and more of a implementation issue of the ** operator. Therefore, this is not a duplicate of questions which are only asking about floating point issues such as precision or associativity.


Python relies on the underlying platform for its floating-point arithmetic. I hypothesize that Python’s ** operator uses a pow implementation (as used in C) (confirmed by user2357112 referring to Python 2.7.15 source code).

Generally, pow is implemented by using (approximations of) logarithms and exponentials, in part. This is necessary since pow supports non-integer arguments. (Of course, this general implementation does not preclude specializations for subsets of its domain.)

Microsoft’s pow implementation is notoriously not good. Hence, for pow(a, 2), it may be returning a result not equal to a*a.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: