leriksen has asked for the wisdom of the Perl Monks concerning the following question:
This question flows from an earlier problem I asked about summing to zero. Thanks for the replies.
Reading the perl FAQ, they state
However, 19.95 can't be precisely represented as a binary floating point number,...,
Why not? Surely there is a bit pattern in the IEEE float format that precisely represents 19.95 (1.995E1). If a float is stored in,say, 32 bits on a particulat platfrom, some bits are for the mantissa and some are for the exponent and sign. If 24 bits store the mantissa, isn't there a bit pattern from those 24 bits that precisely represents 1.995 ? Its not like it's a lot of precision.
If that is so, why can't the conversion library get that bit exact. The machine can represent 0.15 to however many decimal places it stores, why can't the conversion library create the correct representation? I understand that _expressions_ will potentially have inaccuracies, like exp(ln(x)) resulting in something very close but not quite x. But a string literal should (in my utopian view) convert precisely. The only exception to this would be a string literal expressing a value beyound the precision of the platform, OS or perl (most restrictive win's)  e.g. "0.1E4096" will _probably_ end up being represented as 0.0E0
Is it related to the binary storage and summing fractional powers of 2 e.g. a2^1 + b2^2 + c2^2 ... where a,b,c... are 1 or 0.
Anyone have a view why string literal conversion of seemingly inoccuous floats has inaccuracies?
Re: Still puzzled by floats
by blakem (Monsignor) on Oct 07, 2002 at 06:30 UTC

The decimal 0.95 can be represented in base 10 as:
9/10 + 5/100
How would you represent that in binary?
1/2 + 1/4 + 1/8 + 1/16 + 0/32 + 0/64 + 1/128 + 1/256 +
0/512 + 0/1024 + 1/2048 + 1/4096 ...
No matter how far you take that series it will *never* be exactly 0.95. The binary representation
of 0.95 takes an infinite number of bits.
0.95_{(10)} ≈ 0.1111 0011 0011 0011 0011 0011 0011_{(2)}
But those last four bits repeat forever. Its exactly like writing 1/3 in base 10:
1/3 ≈ 0.33333333333333333333333333333333_{(10)}
Blake
 [reply] [d/l] [select] 
Re: Still puzzled by floats
by hossman (Prior) on Oct 07, 2002 at 06:25 UTC

However, 19.95 can't be precisely represented as a
binary floating point number,...,
Why not? Surely there is a bit pattern in the IEEE float
format that precisely represents 19.95 (1.995E1). If a
float is stored in,say, 32 bits on a particulat platfrom,
some bits are for the mantissa and some are for the exponent...
That's not how it works.
What you are describing would be a base10 representation 
ie: you store a number and a base 10 exponent. What is
typicaly used is a number and a base 2 exponent.
what you want: 
mantissa * (10 ** exp) 
what you get: 
mantissa * (2 ** exp) 
IEEE 854 specifies support for base10 representations,
but no one uses it  what gets used is
IEEE 754. When you
get a sizable chunk of free time, read through
What Every Computer Scientist Should Know About FloatingPoint Arithmetic 
in the mean time, John Darcy (Sun's floating point guru) has
a great set of
slides
about Floats in java  but the information is equally useful for perl programmers.
 [reply] 
Re: Still puzzled by floats
by abell (Chaplain) on Oct 07, 2002 at 07:04 UTC

A little addition to what others already said:
in base d you can only represent exactly numbers expressed by fractions a/b with b a divisor of some power of d. In other words, to check if a reduced fraction a/b is expressable in finite form (not periodic) in base d, all prime divisors of b must also divide the base d.
Thus, 13/24 has a finite form in base 6, since 24=2^3*3, and both 2 and 3 are factors of 6, but not in base 10 or 2.
1/2 has a finite form in base 2 and 10, but not 3 and so on.
Best regards
Antonio Bellezza
The stupider the astronaut, the easier it is to win the trip to Vega  A. Tucket
 [reply] 
Re: Still puzzled by floats
by BrowserUk (Pope) on Oct 07, 2002 at 06:32 UTC

The simple answer is that some decimal fractions cannot be accurately representred by binary fractions for similar reason as some ordinary fractions cannot be represented using decimal fractions.
1/3 is an exact value, but the closest we can get to representing it as a decimal fraction is 0.3333333333333...
No matter how many 3's you add after the decimal point, you have never quite accurately represented it.
Update: I couldn't work out how to easily show what I was trying to show, and the other posts say what I was trying to illustrate better than I was going to anyway.
Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hallo, Mister ladeda. ... Like yer ring!
 [reply] 

how about if you work the problem the other way.
Base 2 Base 10

.0001 == 0/2 + 0/4 + 0/8 + 1/16 == .0625
.0010 == 0/2 + 0/4 + 1/8 + 0/16 == .125
.0011 == 0/2 + 0/4 + 1/8 + 1/16 == .1875
.0100 == 0/2 + 1/4 + 0/8 + 0/16 == .25
.0101 == 0/2 + 1/4 + 0/8 + 1/16 == .3125
.0110 == 0/2 + 1/4 + 1/8 + 0/16 == .375
.0111 == 0/2 + 1/4 + 1/8 + 1/16 == .4375
.1000 == 1/2 + 0/4 + 0/8 + 0/16 == .5
.1001 == 1/2 + 0/4 + 0/8 + 1/16 == .5625
.1010 == 1/2 + 0/4 + 1/8 + 0/16 == .625
.1011 == 1/2 + 0/4 + 1/8 + 1/16 == .6875
.1100 == 1/2 + 1/4 + 0/8 + 0/16 == .74
.1101 == 1/2 + 1/4 + 0/8 + 1/16 == .8125
.1110 == 1/2 + 1/4 + 1/8 + 0/16 == .875
.1111 == 1/2 + 1/4 + 1/8 + 1/16 == .9375
has you can see there are gaps in between the decimal numbers. The more accurate you want to get the more digits in the base 2 numbers you need. Assuming that you're working with a computer that has 32 bit registers you can only store a finite number so you may not always have enough bits to represent the fraction you want.
jjdraco
learning Perl one statement at a time.
 [reply] 
Re: Still puzzled by floats
by maxomai (Initiate) on Oct 07, 2002 at 16:15 UTC

For what it's worth: you might be able to use Math::FixedPrecision to handle "floating point" data with as much precision as you need.
Generally speaking you probably want something that handles Binary Coded Decimals to handle decimal data flawlessly. Most Intel archtechtures and lots of (other) languages support BCD.
Hope this helps.  [reply] 
Re: Still puzzled by floats
by leriksen (Curate) on Oct 07, 2002 at 23:45 UTC

Thanx everyone, that was brilliant. I had the insight about infinite summation of fractional powers of two a couple of hours after I posted, but it's nice to see so many quality explanations and alternatives.  [reply] 

