Integer Division

Dave Angel davea at ieee.org
Fri Jun 19 08:06:51 EDT 2009


Anjanesh Lekshminarayanan wrote:
>>>> a = 1
>>>> b = 25
>>>> a / b
>>>>         
> 0
>   
>>>> float(a) / b
>>>>         
> 0.040000000000000001
>   
>
>   
>>>> from __future__ import division
>>>> a = 1
>>>> b = 25
>>>> a / b
>>>>         
> 0.040000000000000001
>   
>
> In what simple way can I get just 0.04 ?
>
>   
Your subject line says "Integer Division" but you're dealing with 
floats.  IEEE standard float cannot exactly represent 0.04   In fact, no 
binary floating point value of finite precision can get that exact 
value.  So if you really want 0.04, you need to use the decimal 
package.  It's the only way you'll be sure of exactly representing any 
decimal fraction you need.

Let's call  val = float(1)/25    If you're using future division (or 
Python 3.x), 1/25 will be exactly the same as val.  In either case, the 
division cannot come out exactly, since there is no such exact float.

On the other hand, some *string* representation of val may not come out 
"exact."  Technically, to represent val in decimal digits may take up to 
59 or so characters.  But the two standard conversions from float to 
string ( float.__str__   and float.__val__ ) do a little rounding 
themselves.  So you can try them, and see that one of them "works."  
(print calls the __str__ method, while the interpreter uses __repr__)

The problem with this is that what "works" for one such val might fail 
for the next.  And these __str__ and __val__ have been implemented 
multiple times, so testing on one Python version will not assure 
consistency on the next.

The issue is that you're counting on two approximations canceling each 
other out.  That'll work in some circumstances, but knowing what they 
are isn't reasonable.

So what do people do?  Simplest is to use a decimal package.  I tried 
back in the early 80's to convince the IEEE committee to include decimal 
float in the standard, but was rejected.  I had implemented (microcoded) 
arithmetic and transcendentals on a machine which offered only decimal 
floating point;  no binary floating point.

Next choice?  Stick to integers, or implied fractions.  For example, if 
dealing with dollars and cents, always calculate and store the value in 
pennies, and only insert the decimal when displaying.

Finally, it's not hard (if you know something about the numbers) to get 
a "pretty" display version for yourself, rounding it as you're 
converting to string.

Note that this affects other aspects of your program, such as 
comparisons between two floats.  If you sum up 100 copies of .01, will 
you get exactly 1.0 ?  I don't know, but in many cases, clearly not.

This is not a new problem.  I read about it in McCracken's Fortran book 
in 1967, where he said to use something on the order of:
     if  abs(a-b) < .0000000001 ...

when comparing reals.





More information about the Python-list mailing list