Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

$ 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 specification or what kind of implementation of ** could possibly allow for this.

To address the duplicate flagging: This is most likely not directly an 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.

like image 378
user1658887 Avatar asked Jun 01 '18 19:06

user1658887


People also ask

Why do we use float INF?

As of 2020, there is no such way to represent infinity as an integer in any programming language so far. But in python, as it is a dynamic language, float values can be used to represent an infinite integer. One can use float('inf') as an integer to represent it as infinity.

What is floating point error in Python?

It's a problem caused when the internal representation of floating-point numbers, which uses a fixed number of binary digits to represent a decimal number. It is difficult to represent some decimal number in binary, so in many cases, it leads to small roundoff errors.

Why are floating point calculation in accurate in Python?

The floating-point calculations are inaccurate because mainly the rationals are approximating that cannot be represented finitely in base 2 and in general they are approximating numbers which may not be representable in finitely many digits in any base.

Is Python a float number?

The float type in Python represents the floating point number. Float is used to represent real numbers and is written with a decimal point dividing the integer and fractional parts. For example, 97.98, 32.3+e18, -32.54e100 all are floating point numbers.


1 Answers

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.

like image 118
Eric Postpischil Avatar answered Oct 05 '22 22:10

Eric Postpischil