1

I wonder why

round(1.499999999999999)
1

and

round(1.4999999999999999)
2

And if I want to print it in python console, 1.499999999999999 printed as 1.499999999999999 and 1.4999999999999999 as 1.5

Also for example 1 / 3 is printed as 0.3333333333333333 (with 16 digits after decimal point), is 16 digits after decimal point is maximum amount of digits or it's different how it's stored and how it's printed in python?

mrgloom
  • 20,061
  • 36
  • 171
  • 301

2 Answers2

4

From Floating Point Arithmetic: Issues and Limitations\Representation Error in The Python Tutorial:

Almost all machines today (November 2000) use IEEE-754 floating point arithmetic, and almost all platforms map Python floats to IEEE-754 “double precision”. 754 doubles contain 53 bits of precision, so on input the computer strives to convert 0.1 to the closest fraction it can of the form J/2**N where J is an integer containing exactly 53 bits.

It's likely that your Python implementation uses the IEEE 754 standard to represent numbers where, loosely, all numbers (except NaN and infinity) are represented as

x = f * 2^e

where f and e (you can think of them as the fractional part and the exponent) are integers.


In this case:

  • 1.499999999999999 is represented as 0x3FF7FFFFFFFFFFFB.

    This corresponds to 6755399441055739*2^-52 which is exactly 1.4999999999999988897769753748434595763683319091796875.

  • 1.4999999999999999 is represented as 0x3FF8000000000000.

    This corresponds to 6755399441055744*2^-52 which is exactly 1.5.

The reason that 1.4999999999999999 is represented as 1.5 in Python is because 1.5 is the closest value that can be represented in IEEE 754 to 1.4999999999999999.


As the standard only represents a finite number of values (it effectively discretises the real number line to a fixed number of points) compromises must be made when a number that does not lie exactly on one of those points.

1.499999999999999 is sandwiched between two numbers that can be represented in IEEE 754 - you can look at it as

6755399441055739*2^-52 is closest to 1.499999999999999 (note that the fractional part is smaller than 0.5, so rounding down is chosen).

Likewise, 1.4999999999999999 is sandwiched between two numbers that can be represented in IEEE 754 - you can look at it as

6755399441055744*2^-52 is closest to 1.4999999999999999 (note that the fractional part is greater than 0.5, so rounding up is chosen) so the IEEE 754 representation equivalent to 1.5 is chosen.


To answer your question, the results are

round(1.499999999999999)
1

and

round(1.4999999999999999)
2

because the second statement is functionally the same as

round(1.5)
2

since 1.4999999999999999 and 1.5 are treated as identical - you can probably confirm this by doing something like

1.4999999999999999 == 1.5

Note: I'll emphasise that this is dependent on the Python implementation that you're running implementing IEEE 754 for its floating-point numbers.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
1

That's because python isnt as much accurate so 1.49999999999999999999999999999 = 1.5 ---> round(1.5) = 2 read more about it there https://docs.python.org/3/tutorial/floatingpoint.html if u want

for more accuratte calculation math library can help for example: 0.1 + 0.1 + 0.1... = 1 and in python is 0.999999999999 so try
print(math.fsum([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]))

Mwt_0239
  • 342
  • 1
  • 3
  • 10