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