Subject: Re: atof returns a value that is slightly greater than the original string
From: James Youngman <[email-masked]>
To: Marco Craveiro <[email-masked]>
Cc: [email-masked]
Date: 10 Sep 2001 22:12:00 +0100

Marco Craveiro <[email-masked]> writes:

> int main (void)
> {
> float f = atof ("695.40");
> 
> cout << f;
> }
> 
> (gdb) p f
> $2 = 695.400024         ----> after assignment

> 
> since I need this the data to generate a sum, the sum ends up a bit off
> because of this. and unfortunatelly, because there is so many people
> with the #include problem, its impossible to search the web properly.
> I'm sure its something i'm doing (or not doing), just can't see
> what...

This is not a bug in Cygwin.  This is because of the fact that a float
is almost never an exact representation of a decimal number.

Each bit in a float represents a power of two which is either added to
the total value, or not.  

Hence 695 can be represented exactly in binary as 1010110111, but 
the extra 0.4 is a problem.   Using a fairly large number of binary
digits, you can get quite close :-

shell $ ( echo obase=2; echo scale=30; echo 6954/10 ) | bc

1010110111.011001100110011001100110011001100110011001100110011001100\
1100110011001100110011001100110011001100110

...but of course this is not exact (the backslashes here are just for
readability).  

Unfortunately there are only 32 bits of data in a float, so the
approximation used in a float is even less.   If we change your
program to use more precise types we get the following results :-

float             695.400024
double            695.39999999999998
long double       695.39999999999997726263245567679405

If you want more precision still, you can use Bruno Haible's excellent
CLN library (which is written in C++ and provides a good C++ API for
extended precision arithmetic, and was originally written in order to
provide Common Lisp bignum support).

If you need "infinite" precision, CLN also offers a 'rational'
representation which would represent "695.4" as "6954/10".  However,
as you continue to calculate with rational values, the large number of
digits used on the top and bottom of the fraction can use lots of RAM
up.  There are also lots of things you can't use rational arithmetic
for, for example trigonometry or root extraction.

The other place to look for an explanation of this problem is the FAQ
lists for the comp.lang.c and comp.lang.c++ newsgroups. See
ftp://rtfm.mit.edu/.

-- 
James Youngman
Manchester, UK.  +44 161 226 7339
PGP (GPG) key ID for <[email-masked]> is 64A95EE5 (F1B83152).

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/