Why doesn't atof work?

D

Drew

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;
}
 
R

Ron Natalie

Drew said:
//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.
 
J

Jeff Schwab

Drew said:
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.
 
D

Drew

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 said:
Drew said:
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.
 
D

Drew

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 said:
Drew said:
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.
 
D

David Harmon

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
 
M

MPBroida

Drew said:
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
 
B

Bret Pehrson

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

write:

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

read:

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

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 said:
Drew said:
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.
 
J

Jeff Schwab

Drew said:
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




Drew said:
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::eek:fstream out( "file" );

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

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

double read( )
{
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;
}
 
B

Bret Pehrson

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 said:
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.
 
J

Jeff Schwab

Bret said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top