Python can't divide??!?!

D

Dan Williams

Ummmm...

This is weird. Sorry if it's known about (how can it NOT be, I wonder?) but
I haven't seen any reference to it anywhere.

I'm running the latest Python (2.3.3) on Windows XP Pro, i386 architecture.

Fire up python or whatever.

Do this: Result:

3 / 5 0 Fair enough, int / int = int
3 / 5.0 0.59999999999999998 eh?
3.0 / 3 0.59999999999999998 ummmm...
3.0 / 5.0 0.59999999999999998 how did I guess...

That's just an example. Python cannot divide. Period. If you try 1.0 / 3 you
get 0.33333333333333331, and from this, the above example, and a few tests,
I speculate that *something* is subtracting 2 from the last digit *after*
the division is done.

Wacky.

Now, is this just me, or can someone else duplicate it? I've tried it on two
computers here, but they're both Win XP. I'm about to test it on Linux but I
figured I'd write this first.

Dan
 
S

Stephen Boulet

Works fine here:
0.000000 0.600000 1.000000 0.600000

but
0.00000000000000000 0.59999999999999998 1.00000000000000000
0.59999999999999998

;)

Stephen
 
D

Dan Bishop

Dan Williams said:
Ummmm...

This is weird. Sorry if it's known about (how can it NOT be, I wonder?) but
I haven't seen any reference to it anywhere.

Then you haven't been looking hard enough.
I'm running the latest Python (2.3.3) on Windows XP Pro, i386 architecture.

Fire up python or whatever.

Do this: Result:

3 / 5 0 Fair enough, int / int = int

This is for bug-compatibility with old versions of Python. It is
strongly recommended that all new Python scripts use "from __future__
import division".
3 / 5.0 0.59999999999999998 eh?
3.0 / 3 0.59999999999999998 ummmm...
3.0 / 5.0 0.59999999999999998 how did I guess...

It makes perfect sense when you remember that computers do math in
binary. In binary, 3/5 is equal to 0.1 0011 0011 0011 0011 0011
0011..., which is rounded to (C99 notation) 0x1.33333333333333333p-1.
The exact decimal equivalent of this is
0.59999999999999997779553950749686919152736663818359375. In the
default 17 significant digits format, this rounds to
0.59999999999999998.
That's just an example. Python cannot divide. Period.

It's off by only 37 parts per quintillion.
If you try 1.0 / 3 you get 0.33333333333333331,

More precisely, you get 0x1.5555555555555p-2, or
0.333333333333333314829616256247390992939472198486328125.
and from this, the above example, and a few tests,
I speculate that *something* is subtracting 2 from the last digit *after*
the division is done.

*Nothing* is subtracting from the last digit because your floating
part hardware has no concept of decimal digits, only bits.
Now, is this just me, or can someone else duplicate it?

Everyone in the world who has binary floating part hardware can
duplicate it, whether they're using Python or not.
 
E

Erik Max Francis

Dan said:
Fire up python or whatever.

Do this: Result:

3 / 5 0 Fair enough, int / int = int
3 / 5.0 0.59999999999999998 eh?
3.0 / 3 0.59999999999999998 ummmm...
3.0 / 5.0 0.59999999999999998 how did I guess...

That's just an example. Python cannot divide. Period.

Neither can C, C++, Java, Perl, or any of the other countless
programming languages which use floating point.
 
K

Kurt B. Kaiser

Dan Williams said:
Fire up python or whatever.

Do this: Result:

3 / 5 0 Fair enough, int / int = int
3 / 5.0 0.59999999999999998 eh?
3.0 / 3 0.59999999999999998 ummmm...
3.0 / 5.0 0.59999999999999998 how did I guess...
[...]

Wacky.

:)
 
J

Josiah Carlson

Wacky.

Not wacky, there is a difference between str() and repr():
'0.59999999999999998'


- Josiah
 
J

John Hunter

This prints a float 0.6

This prints a tuple of floats (0.59999999999999998, 0.59999999999999998)

This prints a (length 1) tuple of floats (0.59999999999999998,)

The thing that may be tripping you up is that (val) is simply the
value, and (val,) is a tuple containing the value as the first
element. As for printing a value versus a tuple of values, that's the
__repr__ versus __str__ distinction previous posters have referred to.

JDH
 
K

Kurt B. Kaiser

John Hunter said:
The thing that may be tripping you up is that (val) is simply the
value, and (val,) is a tuple containing the value as the first
element. As for printing a value versus a tuple of values, that's the
__repr__ versus __str__ distinction previous posters have referred to.

:)

Tim enlightened me on this issue some years ago, when I suggested a
"solution" using sys.displayhook;

http://www.google.com/groups?q=g:[email protected]

Just try explaining this stuff to a 9 year old learning Python! It
tends to break the expository flow....
 
J

Josiah Carlson

Axle said:
Yes, python can divide... use the / operator

He was referring to the inaccuracy of binary vs. decimal
representations. Most Computer Science students don't learn about it
until sophomore year of college in their computer architectures class.


3.0 / 5.0 -> .6 in decimal.

When we're dealing with floating point arithmetic in Python (or any
other language that uses IEEE 754 double-precision floating point
representations), 3.0 / 5.0 is internally represented as:
0011111111100011001100110011001100110011001100110011001100110011

If we then convert that back into decimal, we get .59999999999999998.

Binary representation thanks to:
http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html

- Josiah
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,173
Latest member
GeraldReund
Top