mondev
mondev

Reputation: 31

Casting float to int results in incorrect value

The result variable will hold the value 9.0. Why then when I print using "%d" does print return 8?

result = (((1.7526 % 0.3048) / 0.3048) * 12)
print(result)        #prints 9.0
print("%f" % result) #prints 9.0
print("%d" % result) #prints 8

Upvotes: 3

Views: 1069

Answers (2)

David Heffernan
David Heffernan

Reputation: 612794

Floating point arithmetic is inherently imprecise. In Python calculations are typically performed to double precision. Your numbers are not exactly representable to double precision and so are subject to rounding errors. On my machine, result is 8.9999999999999929.

>>> result = (((1.7526 % 0.3048) / 0.3048) * 12)
>>> result
8.9999999999999929
>>> print result
9.0
>>> int(result)
8

When you print the value it gets rounded to 9.0, but the actual value stored in result in less than 9.0. So, when you convert result to an integer, it is truncated to 8.

The key issue is that of representability of values. Neither 1.7526 nor 0.3048 are exactly representable in double precision as can easily be seen in the Python interpreter.

>>> 1.7526
1.7525999999999999
>>> 0.3048
0.30480000000000002

The moral of the story is that you should not expect exact arithmetic when using floating point values. The seminal discussion of this topic is: What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Upvotes: 6

Levon
Levon

Reputation: 143017

The %d truncates your value which is why you get 8.

Floating point representation in a binary system is an approximation meaning the value that displayed at 9.0 was internally less than 9 and therefore truncated down to 8.

For example all of these yield 3.

In [19]: i = 3.1
In [20]: print '%d' %i
3

In [21]: i = 3.4
In [22]: print '%d' %i
3

In [23]: i = 3.7
In [24]: print '%d' %i
3

In [25]: i = 3.9999
In [26]: print '%d' %i
3

This Wikipeadia article provides some additional background on floating point representation.

Upvotes: 1

Related Questions