views:

242

answers:

2

I encountered a weird behaviour in Perl. The following subtraction should yield zero as result (which it does in Python):

print 7.6178E-01 - 0.76178
-1.11022302462516e-16

Why does it occur and how to avoid it?

P.S. Effect appears on "v5.10.0 built for x86_64-linux-gnu-thread-multi" (Ubuntu 9.04) and "v5.8.9 built for darwin-2level" (Mac OS 10.6)

+2  A: 

It's presumably down to the way the Perl interpreter converts the numeric literal to a floating point value - clearly it doesn't recognise these as the same number pre-conversion. Perhaps it's representing the 7.6178 as a float and then dividing by 10? This could result in subtly different bit representations.

It could also vary between different Perl interpreters.

David M
+8  A: 

It's not that scientific notation affects the precision so much as the limitations of floating point notation represented in binary. See the answers to the perlfaq4. This is a problem for any language that relies on the underlying architecture for number storage.

If you need better number handling, check out the bignum pragma.

brian d foy
Ok, use bignum does the trick. However, I refuse to accept this behaviour as normal, regardless of any binary representation issues. Any other language handles this correctly.
Simon
Not all languages store numbers the same, and I didn't say anything about it being normal.
brian d foy
Simon - any language that isn't demonstrating these sort of issues in at least SOME corner cases is either not using the CPU floating-point instructions or is not handling floating-point numbers correctly. Unfortunately, incorrect handling of numbers is relatively normal (at leats as far as conversion between base-10 fractional numbers and floating-point numbers).
Vatine
This answer is true, but doesn't address the question of why two different literals expressing the same number are being stored as two different representations.
darch
They aren't the same number to the computer. You translate them to mean the same number, but that's not how it works in the silicon. David M already explained that.
brian d foy
I wouldn't really say David *explained* it, Brian. Rather, he offered some ideas about what *might* be true. Is his suggestion *really* how the compiler parses scientific-notation literals? Is it code shared by all Perl interpreters, or do some versions do it differently?
Rob Kennedy
The read code for yourself. It's all in either perl.h or numeric.c. It boils down to who implements your atof, which depends on how you compiled the source. No matter which way you compile, you're at the mercy of how the local architecture handles multiplication or division. What David M. describes is what Perl does.
brian d foy