Garbage in floating point numbers?

Garbage in floating point numbers?

Post by Rajarshi Bandyopadhya » Thu, 24 Jun 1999 04:00:00



Hi all,

Please take a look at the following 3-line program.

main(){
        float t=0.001;
        float u=1/t;
        printf("%f\n",u);  //u expected to be 1000

Quote:}

The actual output is 999.999939.
On debugging using gdb, we find that t is actually assigned as
0.00100000005. This seems to be the cause of the discrepancy.

What is the reason for this garbage at the tail of the fp number?
I am writing a program which depends on the precise values of fp
numbers and this problem is f****ing it all up!

How do I get around it?

TIA,
Rajarshi

 
 
 

Garbage in floating point numbers?

Post by Lew Pitch » Thu, 24 Jun 1999 04:00:00


You've discovered the wonderfull world of floatingpoint math.

To make a long explanation short, floating point numbers aren't precise;
depending on the value, they may round or truncate the expected number

It's just an artifact of floatingpoint; live with it.


>Hi all,

>Please take a look at the following 3-line program.

>main(){
>    float t=0.001;
>    float u=1/t;
>    printf("%f\n",u);  //u expected to be 1000
>}

>The actual output is 999.999939.
>On debugging using gdb, we find that t is actually assigned as
>0.00100000005. This seems to be the cause of the discrepancy.

>What is the reason for this garbage at the tail of the fp number?
>I am writing a program which depends on the precise values of fp
>numbers and this problem is f****ing it all up!

>How do I get around it?

>TIA,
>Rajarshi

Lew Pitcher
System Consultant, Integration Solutions Architecture
Toronto Dominion Bank


(Opinions expressed are my own, not my employer's.)

 
 
 

Garbage in floating point numbers?

Post by UNiDo » Thu, 24 Jun 1999 04:00:00



> Hi all,
> Please take a look at the following 3-line program.
> main(){
> float t=0.001;
> float u=1/t;
> printf("%f\n",u);  file://u expected to be 1000
> }
> The actual output is 999.999939.
> On debugging using gdb, we find that t is actually assigned as
> 0.00100000005. This seems to be the cause of the discrepancy.

> What is the reason for this garbage at the tail of the fp number?
> I am writing a program which depends on the precise values of fp
> numbers and this problem is f****ing it all up!

> How do I get around it?

Use   double   for both variables... which will use 64 bits for them (not 32
like with float)
This happens because the 32 bit variable uses 1 bit for the sign of the
exponent, 1 bit for the sign of the actual number, 7 bits for the
exponent... and only 23 bit for the number (actualy 24 since the first 1
isn't stored).
0.001(dec) = 0.0000000001000001100010010011011101001...... etc (or
something).... (0.001 can not be stored correctly binary, if i didn't
miscaclulate)
which means the computer stores 0.1000001100010010011011101001.... x10^9
or + 0.10000...... (24 digits) x 10^(+9)
So, when you calculate something with it, you'll only have something like
0.009999999
Solutions... take more bits to store the variables or use other formulas

Hope this makes sense :)
UNiDoG

 
 
 

Garbage in floating point numbers?

Post by Bob Tinsle » Fri, 25 Jun 1999 04:00:00




> > Hi all,
> > Please take a look at the following 3-line program.
> > main(){
> > float t=0.001;
> > float u=1/t;
> > printf("%f\n",u);  file://u expected to be 1000
> > }
> > The actual output is 999.999939.
> > On debugging using gdb, we find that t is actually assigned as
> > 0.00100000005. This seems to be the cause of the discrepancy.

> > What is the reason for this garbage at the tail of the fp number?
> > I am writing a program which depends on the precise values of fp
> > numbers and this problem is f****ing it all up!

> > How do I get around it?

> Use   double   for both variables... which will use 64 bits for them (not 32
> like with float)
> This happens because the 32 bit variable uses 1 bit for the sign of the
> exponent, 1 bit for the sign of the actual number, 7 bits for the
> exponent... and only 23 bit for the number (actualy 24 since the first 1
> isn't stored).
> 0.001(dec) = 0.0000000001000001100010010011011101001...... etc (or
> something).... (0.001 can not be stored correctly binary, if i didn't
> miscaclulate)
> which means the computer stores 0.1000001100010010011011101001.... x10^9
> or + 0.10000...... (24 digits) x 10^(+9)
> So, when you calculate something with it, you'll only have something like
> 0.009999999
> Solutions... take more bits to store the variables or use other formulas

Alternative if you need an *exact* representation: hunt down a decent
library
for rational arithmetic.

Cheers,

        -- Bob

- Show quoted text -

Quote:

> Hope this makes sense :)
> UNiDoG

 
 
 

Garbage in floating point numbers?

Post by Ewald Pf » Fri, 25 Jun 1999 04:00:00


RB>    float t=0.001;
RB>    float u=1/t;
RB>    printf("%f\n",u);  //u expected to be 1000
RB> The actual output is 999.999939.

Migrate to integers if you want precision. As a saying goes: you didn't
understand the problem if you cannot express it with integers ;)

 
 
 

Garbage in floating point numbers?

Post by Thomas Bogg » Fri, 25 Jun 1999 04:00:00




> > Hi all,
> > Please take a look at the following 3-line program.
> > main(){
> > float t=0.001;
> > float u=1/t;
> > printf("%f\n",u);  file://u expected to be 1000
> > }
> > The actual output is 999.999939.
> > On debugging using gdb, we find that t is actually assigned as
> > 0.00100000005. This seems to be the cause of the discrepancy.

> > What is the reason for this garbage at the tail of the fp number?
> > I am writing a program which depends on the precise values of fp
> > numbers and this problem is f****ing it all up!

> > How do I get around it?

> Use   double   for both variables... which will use 64 bits for them (not 32
> like with float)
> This happens because the 32 bit variable uses 1 bit for the sign of the
> exponent, 1 bit for the sign of the actual number, 7 bits for the
> exponent... and only 23 bit for the number (actualy 24 since the first 1
> isn't stored).
> 0.001(dec) = 0.0000000001000001100010010011011101001...... etc (or
> something).... (0.001 can not be stored correctly binary, if i didn't
> miscaclulate)
> which means the computer stores 0.1000001100010010011011101001.... x10^9
> or + 0.10000...... (24 digits) x 10^(+9)
> So, when you calculate something with it, you'll only have something like
> 0.009999999
> Solutions... take more bits to store the variables or use other formulas

> Hope this makes sense :)
> UNiDoG

That's not actually the correct IEEE floating point representation.  The
exponent is eight bits and is biased by half of its maximum value (32 bit float
is biased by 127), so that a binary exponent of 00000000 equates to -127.  The
point is that there is no sign bit for the exponent.

-thomas

 
 
 

Garbage in floating point numbers?

Post by Martin Colli » Fri, 25 Jun 1999 04:00:00


On Wed, 23 Jun 1999 19:32:57 +0000, Rajarshi Bandyopadhyay


>What is the reason for this garbage at the tail of the fp number?
>I am writing a program which depends on the precise values of fp
>numbers and this problem is f****ing it all up!

>How do I get around it?

You could either replace your binary computer with a decimal one or
use an arbitrary precision library such as gmp.

Martin
_________________________________________________________________
We see here a curious instance of that frequent mental phenomenon
:- the precise inversion of the truth by a superficial view.
                                          Benjamin R. Tucker 1899

 
 
 

Garbage in floating point numbers?

Post by Johan Kullsta » Fri, 25 Jun 1999 04:00:00



> Hi all,

> Please take a look at the following 3-line program.

> main(){
>    float t=0.001;
>    float u=1/t;
>    printf("%f\n",u);  //u expected to be 1000
> }

> The actual output is 999.999939.
> On debugging using gdb, we find that t is actually assigned as
> 0.00100000005. This seems to be the cause of the discrepancy.

yes.  0.001 has a repeating (ie non-terminating) binary expansion.  it
has been approximated.  consider representing 1/7 in a decimal
scientific notation system with finite precision.

Quote:> What is the reason for this garbage at the tail of the fp number?
> I am writing a program which depends on the precise values of fp
> numbers and this problem is f****ing it all up!

sorry.  i think you are bringing unreasonable expectations as to what
floating point is, what it can do for you and how to work with it.

Quote:> How do I get around it?

expect floating point values to be approximate and program accordingly.

--
johan kullstam

 
 
 

Garbage in floating point numbers?

Post by Johan Kullsta » Fri, 25 Jun 1999 04:00:00




> RB>    float t=0.001;
> RB>    float u=1/t;
> RB>    printf("%f\n",u);  //u expected to be 1000
> RB> The actual output is 999.999939.

> Migrate to integers if you want precision. As a saying goes: you didn't
> understand the problem if you cannot express it with integers ;)

allow me to introduce such concepts as
1) the ratio of the circumference to the diameter of a cirle,
2) the base of the natural logarithm,
3) the square root of two.

--
johan kullstam

 
 
 

Garbage in floating point numbers?

Post by David B Anders » Fri, 25 Jun 1999 04:00:00





>> Hi all,

>> Please take a look at the following 3-line program.

>> main(){
>>        float t=0.001;
>>        float u=1/t;
>>        printf("%f\n",u);  //u expected to be 1000
>> }

>> The actual output is 999.999939.
>> On debugging using gdb, we find that t is actually assigned as
>> 0.00100000005. This seems to be the cause of the discrepancy.

>yes.  0.001 has a repeating (ie non-terminating) binary expansion.  it
>has been approximated.  consider representing 1/7 in a decimal
>scientific notation system with finite precision.

>> What is the reason for this garbage at the tail of the fp number?
>> I am writing a program which depends on the precise values of fp
>> numbers and this problem is f****ing it all up!

>sorry.  i think you are bringing unreasonable expectations as to what
>floating point is, what it can do for you and how to work with it.

Rajarshi Bandyopadhyay should read
  "What Every Computer Scientist Should Know About Floating-Point
  Arithmetic"
  By David Goldberg
  ACM Computing Surveys, Vol 23, No 1, March 1991
as it's a classic and will help explain why
Johan Kullstam is correct.

  "How to Print Floating-Point Numbers Accurately
  Guy L. Steele Jr and Jon L. White
  PLDI, 1990, June 1990 proceedings
and
  "How to Read Floating Point Numbers Accurately"
  William D. Clinger
  PLDI, 1990, June 1990 proceedings
are interesting, though focused on the problems
indicated by their respective titles.

Regards,

 
 
 

Garbage in floating point numbers?

Post by Matthew Carl Schumake » Fri, 25 Jun 1999 04:00:00


> >> Hi all,

> >> Please take a look at the following 3-line program.

> >> main(){
> >>   float t=0.001;
> >>   float u=1/t;
> >>   printf("%f\n",u);  //u expected to be 1000
> >> }

> >> The actual output is 999.999939.
> >> On debugging using gdb, we find that t is actually assigned as
> >> 0.00100000005. This seems to be the cause of the discrepancy.

> Rajarshi Bandyopadhyay should read
>   "What Every Computer Scientist Should Know About Floating-Point
>   Arithmetic"
>   By David Goldberg
>   ACM Computing Surveys, Vol 23, No 1, March 1991
> as it's a classic and will help explain why
> Johan Kullstam is correct.

>   "How to Print Floating-Point Numbers Accurately
>   Guy L. Steele Jr and Jon L. White
>   PLDI, 1990, June 1990 proceedings
> and
>   "How to Read Floating Point Numbers Accurately"
>   William D. Clinger
>   PLDI, 1990, June 1990 proceedings
> are interesting, though focused on the problems
> indicated by their respective titles.

> Regards,


If you don't mind spending some $ you could go out an buy a scientific
math library, especially one that does can do it symbolically(like MatLab)
but I bet there is probably already a free library for linux(anybody know
of one?)
 
 
 

Garbage in floating point numbers?

Post by Ewald Pf » Fri, 25 Jun 1999 04:00:00


JK> allow me to introduce such concepts as

JK> 1) the ratio of the circumference to the diameter of a cirle,
JK> 2) the  base of the natural logarithm,

You may approach such constants as fractions of integers. Calculation
with it goes by scaling (multiplication to a multiprecision product and
divsion back to the original precision). Up to a result with a precision
in the desired word-size.

JK> 3) the square root of two.

There is a nice algorithm around.

For sure there are applications for floating point. But too often it
turns out to be laziness: One may understand the computer to _help_
doing the algebra, but there are too many invitations to take this for
_doing_ the algebra (invitations mainly by programmer's algebraic
notations) - there's a gap in between. Quite often integers may help for
better accuracy even if some decimal points arrive in used figures.

 
 
 

Garbage in floating point numbers?

Post by Gordon Haverlan » Tue, 29 Jun 1999 04:00:00



> Hi all,

> Please take a look at the following 3-line program.

> main(){
>         float t=0.001;
>         float u=1/t;
>         printf("%f\n",u);  //u expected to be 1000
> }

> The actual output is 999.999939.

The actual number output will be architecture dependent.

Quote:> On debugging using gdb, we find that t is actually assigned as
> 0.00100000005. This seems to be the cause of the discrepancy.

Ummm, yes and no.

Quote:> What is the reason for this garbage at the tail of the fp number?
> I am writing a program which depends on the precise values of fp
> numbers and this problem is f****ing it all up!

The reason is your misunderstanding of floating point arithmetic.

Computers run on base 2 arithmetic, and numbers like 0.1 cannot
be exactly written out in base 2 arithmetic in 32, 64 or 80
bits.  Sort of like why 1/3 can't be written out exactly in
base 10 arithmetic.

If you want to learn more about this sort of thing, best to
visit your local library and get a book on numerical methods.

But, from a more practical side, there are a couple of approaches.
You might be able to work with fixed place arithmetic.  In other
words, if everything you do is a multiple of 0.001, then multiply
everything by 1000 and use integers for representing everything.

If you need to use floating point numbers, you might be able to
use one of the specialised libraries out there.  There are
libraries which use binary coded decimal to represent numbers,
instead of base 2 IEEE arithmetic.  There are also extended precision
libraries which use more bits to specify the number, which may
help in avoiding roundoff errors.  The GNU project has one
of these (or more).  Doing this will likely slow down your
application, as your library is going to have to do the math
that would normally be done by floating point hardware.

This should be a start.
Gord.
#include <disclaimer.h>

 
 
 

Garbage in floating point numbers?

Post by Peter Gavi » Tue, 29 Jun 1999 04:00:00


Quote:> If you don't mind spending some $ you could go out an buy a scientific
> math library, especially one that does can do it symbolically(like MatLab)
> but I bet there is probably already a free library for linux(anybody know
> of one?)

Well, if you *really* want to go overkill on this one, you could use
GMP, the GNU Multiple Precision library... :)
(ftp://ftp.gnu.org/gnu/gmp)

Pete