# Why doesn't atof work?

Discussion in 'C++' started by Drew, Jan 20, 2004.

1. ### DrewGuest

Hi:

I'm having trouble getting atof() to accurately convert "3.1"
Any ideas?

Thank you,

Drew

#include <iostream>
#include <math.h>

using namespace std;

int main(int argc, char* argv[])
{

float fNum;
char cNumBuffer[]="3.1";
fNum =(float)atof(cNumBuffer);
//Why does this store 3.099999905 in fNum

return 0;
}

Drew, Jan 20, 2004

2. ### Ron NatalieGuest

"Drew" <> wrote in message news:JShPb.31911\$...
> //Why does this store 3.099999905 in fNum
>

Because that is the closest representable number (3.1 is almost surely not exactly
representable in binary) after it's been converted back to decimal for printing.

Ron Natalie, Jan 20, 2004

3. ### Jeff SchwabGuest

Drew wrote:
> Hi:
>
> I'm having trouble getting atof() to accurately convert "3.1"
> Any ideas?
>
>
>
> Thank you,
>
>
>
> Drew
>
>
>
>
>
> #include <iostream>
> #include <math.h>
>
> using namespace std;
>
> int main(int argc, char* argv[])
> {
>
> float fNum;
> char cNumBuffer[]="3.1";
> fNum =(float)atof(cNumBuffer);
> //Why does this store 3.099999905 in fNum
>
> return 0;
> }
>
>

What Ron said. Furthermore, 3.1 is provably unrepresentable as the
traditional sum of a finite sequence of integer powers of two, since .1
= 10^-1, and 10 has a prime factor other than two.

The GCC maintainers list this as their most often reported non-bug.

http://gcc.gnu.org/bugs.html#nonbugs

You can get a specified number of significant or reliable digits using
sprintf, or a more type-safe alternative. If you need to represent
rational numbers with absolute accuracy, get a library that supports
"common fractions." If you need to represent irrationals perfectly, you
might start by searching for "continued fractions;" these will help with
some of the non-transcendentals.

Personally, I avoid floating-point numbers whenever possible. Von
Neumann also thought any programmers worth their salt should be able to
keep track of a radix point. If you must work with floating point
numbers in the same way you work with integers (e.g., you want to
compare them for equality), at least be careful to round them to a
realistic number of significant digits first.

Jeff Schwab, Jan 20, 2004
4. ### DrewGuest

Thank you all for the great responces.
This was the first time I had ever tried this group.
Lots of smart people here!

If I may, one last question?
Suppose you wanted to write your floats to a text file and read them back
exactly, how would you do it?

Thank you.

Drew

"Jeff Schwab" <> wrote in message
news:...
> Drew wrote:
> > Hi:
> >
> > I'm having trouble getting atof() to accurately convert "3.1"
> > Any ideas?
> >
> >
> >
> > Thank you,
> >
> >
> >
> > Drew
> >
> >
> >
> >
> >
> > #include <iostream>
> > #include <math.h>
> >
> > using namespace std;
> >
> > int main(int argc, char* argv[])
> > {
> >
> > float fNum;
> > char cNumBuffer[]="3.1";
> > fNum =(float)atof(cNumBuffer);
> > //Why does this store 3.099999905 in fNum
> >
> > return 0;
> > }
> >
> >

>
>
> What Ron said. Furthermore, 3.1 is provably unrepresentable as the
> traditional sum of a finite sequence of integer powers of two, since .1
> = 10^-1, and 10 has a prime factor other than two.
>
> The GCC maintainers list this as their most often reported non-bug.
>
> http://gcc.gnu.org/bugs.html#nonbugs
>
> You can get a specified number of significant or reliable digits using
> sprintf, or a more type-safe alternative. If you need to represent
> rational numbers with absolute accuracy, get a library that supports
> "common fractions." If you need to represent irrationals perfectly, you
> might start by searching for "continued fractions;" these will help with
> some of the non-transcendentals.
>
> Personally, I avoid floating-point numbers whenever possible. Von
> Neumann also thought any programmers worth their salt should be able to
> keep track of a radix point. If you must work with floating point
> numbers in the same way you work with integers (e.g., you want to
> compare them for equality), at least be careful to round them to a
> realistic number of significant digits first.
>

Drew, Jan 20, 2004
5. ### DrewGuest

Thank you for the great responces.
This was the first time I had ever been to this group.
Lots of smart people here!

One more question:
How can you save some floats to a text file and read them back acurately?

Thank you.
Best regards,

Drew

"Jeff Schwab" <> wrote in message
news:...
> Drew wrote:
> > Hi:
> >
> > I'm having trouble getting atof() to accurately convert "3.1"
> > Any ideas?
> >
> >
> >
> > Thank you,
> >
> >
> >
> > Drew
> >
> >
> >
> >
> >
> > #include <iostream>
> > #include <math.h>
> >
> > using namespace std;
> >
> > int main(int argc, char* argv[])
> > {
> >
> > float fNum;
> > char cNumBuffer[]="3.1";
> > fNum =(float)atof(cNumBuffer);
> > //Why does this store 3.099999905 in fNum
> >
> > return 0;
> > }
> >
> >

>
>
> What Ron said. Furthermore, 3.1 is provably unrepresentable as the
> traditional sum of a finite sequence of integer powers of two, since .1
> = 10^-1, and 10 has a prime factor other than two.
>
> The GCC maintainers list this as their most often reported non-bug.
>
> http://gcc.gnu.org/bugs.html#nonbugs
>
> You can get a specified number of significant or reliable digits using
> sprintf, or a more type-safe alternative. If you need to represent
> rational numbers with absolute accuracy, get a library that supports
> "common fractions." If you need to represent irrationals perfectly, you
> might start by searching for "continued fractions;" these will help with
> some of the non-transcendentals.
>
> Personally, I avoid floating-point numbers whenever possible. Von
> Neumann also thought any programmers worth their salt should be able to
> keep track of a radix point. If you must work with floating point
> numbers in the same way you work with integers (e.g., you want to
> compare them for equality), at least be careful to round them to a
> realistic number of significant digits first.
>

Drew, Jan 20, 2004
6. ### David HarmonGuest

On Tue, 20 Jan 2004 16:28:57 -0600 in comp.lang.c++, "Drew"
<> was alleged to have written:
>I'm having trouble getting atof() to accurately convert "3.1"

The usual answer to that is the same in C++ as it is in C, and is
covered in Steve Summit's C FAQ. See the topic "14.1: When I set a
float variable to, say, 3.1, why is printf printing it as 3.0999999?"
It is always good to check the FAQ before posting. You can get the FAQ
at:
http://www.eskimo.com/~scs/C-faq/top.html

David Harmon, Jan 21, 2004
7. ### MPBroidaGuest

Drew wrote:
>
> One more question:
> How can you save some floats to a text file and read them back acurately?

Well, this method is probably not recommended, but it
will get you the EXACT same value, provided you read
in on the same architecture it was printed from.

Print the float using a HEX format with enough digits
to cover the entire variable. Then read it back in
using the same HEX format. What you're doing in this
case is effectively printing the exact BIT representation
of the number using HEX notation. When you read it in
the same way, you reproduce the same bit pattern. THEN
looking at it as a float it will be the same as before.

NOTE: I have not tried this in C/C++, but have done it
in other languages. I'm not sure exactly what you might
have to do (casts/etc) to make the Read step work right.
Play with it awhile and see what you get. If you get
it working, post it here so others can see it.

Mike

MPBroida, Jan 21, 2004
8. ### Bret PehrsonGuest

Depends on the level of precision required. Presuming 1 decimal place:

write:

fprintf(file, "%.1f\n", float_value);

fscanf(file, "%f\n", &float_value);

Drew wrote:
>
> Thank you for the great responces.
> This was the first time I had ever been to this group.
> Lots of smart people here!
>
> One more question:
> How can you save some floats to a text file and read them back acurately?
>
> Thank you.
> Best regards,
>
> Drew
>
> "Jeff Schwab" <> wrote in message
> news:...
> > Drew wrote:
> > > Hi:
> > >
> > > I'm having trouble getting atof() to accurately convert "3.1"
> > > Any ideas?
> > >
> > >
> > >
> > > Thank you,
> > >
> > >
> > >
> > > Drew
> > >
> > >
> > >
> > >
> > >
> > > #include <iostream>
> > > #include <math.h>
> > >
> > > using namespace std;
> > >
> > > int main(int argc, char* argv[])
> > > {
> > >
> > > float fNum;
> > > char cNumBuffer[]="3.1";
> > > fNum =(float)atof(cNumBuffer);
> > > //Why does this store 3.099999905 in fNum
> > >
> > > return 0;
> > > }
> > >
> > >

> >
> >
> > What Ron said. Furthermore, 3.1 is provably unrepresentable as the
> > traditional sum of a finite sequence of integer powers of two, since .1
> > = 10^-1, and 10 has a prime factor other than two.
> >
> > The GCC maintainers list this as their most often reported non-bug.
> >
> > http://gcc.gnu.org/bugs.html#nonbugs
> >
> > You can get a specified number of significant or reliable digits using
> > sprintf, or a more type-safe alternative. If you need to represent
> > rational numbers with absolute accuracy, get a library that supports
> > "common fractions." If you need to represent irrationals perfectly, you
> > might start by searching for "continued fractions;" these will help with
> > some of the non-transcendentals.
> >
> > Personally, I avoid floating-point numbers whenever possible. Von
> > Neumann also thought any programmers worth their salt should be able to
> > keep track of a radix point. If you must work with floating point
> > numbers in the same way you work with integers (e.g., you want to
> > compare them for equality), at least be careful to round them to a
> > realistic number of significant digits first.
> >

--
Bret Pehrson
mailto:
NOSPAM - Include this key in all e-mail correspondence <<38952rglkwdsl>>

Bret Pehrson, Jan 22, 2004
9. ### Jeff SchwabGuest

Drew wrote:
> Thank you all for the great responces.
> This was the first time I had ever tried this group.
> Lots of smart people here!
>
> If I may, one last question?
> Suppose you wanted to write your floats to a text file and read them back
> exactly, how would you do it?
>
> Thank you.
>
> Drew
>
>
>
>
> "Jeff Schwab" <> wrote in message
> news:...
>
>>Drew wrote:
>>
>>>Hi:
>>>
>>>I'm having trouble getting atof() to accurately convert "3.1"
>>>Any ideas?
>>>
>>>
>>>
>>>Thank you,
>>>
>>>
>>>
>>>Drew
>>>
>>>
>>>
>>>
>>>
>>>#include <iostream>
>>>#include <math.h>
>>>
>>>using namespace std;
>>>
>>>int main(int argc, char* argv[])
>>>{
>>>
>>> float fNum;
>>> char cNumBuffer[]="3.1";
>>> fNum =(float)atof(cNumBuffer);
>>> //Why does this store 3.099999905 in fNum
>>>
>>> return 0;
>>>}
>>>
>>>

>>
>>
>>What Ron said. Furthermore, 3.1 is provably unrepresentable as the
>>traditional sum of a finite sequence of integer powers of two, since .1
>>= 10^-1, and 10 has a prime factor other than two.
>>
>>The GCC maintainers list this as their most often reported non-bug.
>>
>> http://gcc.gnu.org/bugs.html#nonbugs
>>
>>You can get a specified number of significant or reliable digits using
>>sprintf, or a more type-safe alternative. If you need to represent
>>rational numbers with absolute accuracy, get a library that supports
>>"common fractions." If you need to represent irrationals perfectly, you
>>might start by searching for "continued fractions;" these will help with
>>some of the non-transcendentals.
>>
>>Personally, I avoid floating-point numbers whenever possible. Von
>>Neumann also thought any programmers worth their salt should be able to
>>keep track of a radix point. If you must work with floating point
>>numbers in the same way you work with integers (e.g., you want to
>>compare them for equality), at least be careful to round them to a
>>realistic number of significant digits first.
>>

>
>
>

#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>

struct Exception
{
Exception( char const* p ): m_what( p ) { }
std::string const& what( ) const { return m_what; }
private:
std::string const m_what;
};

void write( double d )
{
std:fstream out( "file" );

if( ! out )
{
throw Exception( "can't write file" );
}

out << std::fixed << std::setprecision( 1000 ) << d;
}

{
std::ifstream in( "file" );

if( ! in )
{
throw Exception( "can't read file" );
}

double d;

in >> d;

return d;
}

int main( )
try
{
float f( .1 );

write( f + 3 );

std::cout << std::fixed << std::setprecision( 1000 ) << read( )
<< "\n";
}
catch( Exception const& x )
{
std::cerr << x.what( ) << '\n';
return 1;
}

Jeff Schwab, Jan 22, 2004
10. ### Bret PehrsonGuest

> Von
> Neumann also thought any programmers worth their salt should be able to
> keep track of a radix point.

Bret thought that any programmer worth their salt would use the *appropriate*
numeric type and not create more work by needlessly keeping track of a radix.

Jeff Schwab wrote:
>
> Drew wrote:
> > Hi:
> >
> > I'm having trouble getting atof() to accurately convert "3.1"
> > Any ideas?
> >
> >
> >
> > Thank you,
> >
> >
> >
> > Drew
> >
> >
> >
> >
> >
> > #include <iostream>
> > #include <math.h>
> >
> > using namespace std;
> >
> > int main(int argc, char* argv[])
> > {
> >
> > float fNum;
> > char cNumBuffer[]="3.1";
> > fNum =(float)atof(cNumBuffer);
> > //Why does this store 3.099999905 in fNum
> >
> > return 0;
> > }
> >
> >

>
> What Ron said. Furthermore, 3.1 is provably unrepresentable as the
> traditional sum of a finite sequence of integer powers of two, since .1
> = 10^-1, and 10 has a prime factor other than two.
>
> The GCC maintainers list this as their most often reported non-bug.
>
> http://gcc.gnu.org/bugs.html#nonbugs
>
> You can get a specified number of significant or reliable digits using
> sprintf, or a more type-safe alternative. If you need to represent
> rational numbers with absolute accuracy, get a library that supports
> "common fractions." If you need to represent irrationals perfectly, you
> might start by searching for "continued fractions;" these will help with
> some of the non-transcendentals.
>
> Personally, I avoid floating-point numbers whenever possible. Von
> Neumann also thought any programmers worth their salt should be able to
> keep track of a radix point. If you must work with floating point
> numbers in the same way you work with integers (e.g., you want to
> compare them for equality), at least be careful to round them to a
> realistic number of significant digits first.

--
Bret Pehrson
mailto:
NOSPAM - Include this key in all e-mail correspondence <<38952rglkwdsl>>

Bret Pehrson, Jan 22, 2004
11. ### Jeff SchwabGuest

Bret Pehrson wrote:
>>Von
>>Neumann also thought any programmers worth their salt should be able to
>>keep track of a radix point.

>
>
> Bret thought that any programmer worth their salt would use the *appropriate*
> numeric type and not create more work by needlessly keeping track of a radix.

And I would agree, provided one understands the limitations of the types
being considered and not just their benefits.

Jeff Schwab, Jan 23, 2004