468,504 Members | 1,979 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,504 developers. It's quick & easy.

string to double conversion - atof() vs istringstream

I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.

Regards,
Harry.

Jul 25 '06 #1
14 8527
Forgot to mention this before. atof() behaviour is expected for -308
exp and that of istringstream is wrong.

Regards,
Harry.

sh**********@gmail.com wrote:
I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.

Regards,
Harry.
Jul 25 '06 #2
sh**********@gmail.com wrote:
I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.
How different are the results? Floating point numbers are notoriously
tricky. See, e.g., these FAQs:

http://www.parashift.com/c++-faq-lit...html#faq-29.16
http://www.parashift.com/c++-faq-lit...html#faq-29.18

Cheers! --M

Jul 25 '06 #3
On 24 Jul 2006 20:12:21 -0700, sh**********@gmail.com wrote:
>I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}
You don't check any return or error value in that function. Moreover,
I would prefer an explicit stringToDoulble() function to a template.
>Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.
Use strtod
(http://www.opengroup.org/onlinepubs/...ns/strtod.html)
and check endptr, errno and return value.

Best wishes,
Roland Pibinger
Jul 25 '06 #4
Roland,
stringToDouble() is definitely something that will resolve the issue,
but that is not I am looking for. I was interested in minimizing the
no. of specialized functions that I write. Moreover, I am using this
only for the intrinsic types. As for the error checking, I don't know
how I can add that with the template types without specializing it for
a certain type.

Regards,
Harish Sharma
Roland Pibinger wrote:
On 24 Jul 2006 20:12:21 -0700, sh**********@gmail.com wrote:
I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

You don't check any return or error value in that function. Moreover,
I would prefer an explicit stringToDoulble() function to a template.
Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.

Use strtod
(http://www.opengroup.org/onlinepubs/...ns/strtod.html)
and check endptr, errno and return value.

Best wishes,
Roland Pibinger
Jul 26 '06 #5
mlimber,
The difference in the values is quite large to be neglected for a
rounding error as the faq says. And anyways I am not interested in
comparing any double type no.s here. The result that I get while using
this func is 2.64167e-308 while atof() returns 2.22507e-308. I
understand that atof() has minimal functionality and that too is type
specific, whereas the istringstream (or istream) has be generic.
However, I think the precision of default 6 digits is lost somewhere
while extracting the value from the string.

Regards,
Harish Sharma

mlimber wrote:
sh**********@gmail.com wrote:
I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.

How different are the results? Floating point numbers are notoriously
tricky. See, e.g., these FAQs:

http://www.parashift.com/c++-faq-lit...html#faq-29.16
http://www.parashift.com/c++-faq-lit...html#faq-29.18

Cheers! --M
Jul 26 '06 #6
sh**********@gmail.com wrote:
Roland,
stringToDouble() is definitely something that will resolve the issue,

Please don't top-post. Your reply belongs following or interspersed
with properly trimmed quotes. See the newsgroup FAQ list:
<http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.4>


Brian
Jul 26 '06 #7
Roland Pibinger wrote:
On 24 Jul 2006 20:12:21 -0700, sh**********@gmail.com wrote:
I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

You don't check any return or error value in that function.
That is a good point. Are you sure the conversion didn't abort
prematurely? Please post a *complete* but *minimal* program (see FAQ
5.8) that demonstrates your problem so we can reproduce it.

Cheers! --M

Jul 26 '06 #8
#include <iostream>
#include <sstream>
#include <cstdlib>

using namespace std;

template<class T>
T value(string s)
{
istringstream(s);
T val; is >val;
return val;
}

int
main()
{
cout << "\natof(2.22507e-308) ->" << atof("2.22507e-308");
cout << "\nvalue<double>(2.22507e-308) ->" <<
value<double>("2.22507e-308");
return 0;
}

Above is the complete demo program illustrating the problem. Actually
the value displayed by the template function is not consistent across
compilation and is sorta random (atleast I didn't see any pattern or
consistent values with every compilation). I checked the output with
MSVC as well as with GCC compiler. They give different values but
neither gives the right output.

Regards,
Harish Sharma

Jul 27 '06 #9
sh**********@gmail.com wrote:
#include <iostream>
#include <sstream>
#include <cstdlib>

using namespace std;

template<class T>
T value(string s)
{
istringstream(s);
T val; is >val;
return val;
}
Try this instead:

class MyException {};

template<class T>
T value(const string& s)
{
istringstream is(s);
T val;
if( !(is >val) || !(is >ws).eof() )
{
throw MyException();
}
return val;
}

Or better, use boost::lexical_cast, which does basically the same thing
'cept better. I get the same answer for both with the above code:

atof(2.22507e-308) ->2.22507e-308
value<double>(2.22507e-308) ->2.22507e-308
>
int
main()
{
cout << "\natof(2.22507e-308) ->" << atof("2.22507e-308");
cout << "\nvalue<double>(2.22507e-308) ->" <<
value<double>("2.22507e-308");
return 0;
}

Above is the complete demo program illustrating the problem. Actually
the value displayed by the template function is not consistent across
compilation and is sorta random (atleast I didn't see any pattern or
consistent values with every compilation). I checked the output with
MSVC as well as with GCC compiler. They give different values but
neither gives the right output.
That's probably because you forgot the variable name for the string
stream (it's using 's', which means you can't access the string that
was passed in and you have a global 'is' somewhere). GIGO.

Cheers! --M

Jul 27 '06 #10
mlimber,

I tried compiling the same program with a later ver of MS C/C++
compiler, which is ...
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42
for 80x86

With this compiler the test program gives expected results. But the GCC
compiler that I am using is gcc version 3.3.1 (mingw special
20030804-1), and it still gives out garbage. And by the way I believe,
there is no garbage i/p in the test program and hence there is no
question of GIGO. Moreover, I don't think there is any need of
exception handling in the test code with the given valid input and I
don't understand how that extra piece of error checking will help. If
your compiler/lib gives you expected results with the given input, it
should behave the same without that as well.

Another simple test to confirm the problem is,

int main() { double d; cin >d; cout << d; return 0; }

Just enter the value 2.22507-308 after compiling with your compiler and
it should show the expected result. But if you try this with the GCC
compiler version that I have mentioned, it gives out garbage. This
piece of code behaves similar to the earlier test program with both the
compilers that I used.

Lastly I tried your changes with GCC and it generates exception and
that tells me that there is some definite issue in the related version
of c++ lib that it is using.

Regards,
Harish Sharma

Jul 29 '06 #11
sh**********@gmail.com wrote:
if your compiler/lib gives you expected results with the given input, it
should behave the same without that as well.
I actually meant, if your compiler/lib gives you expected results with
the give input AND THE ERROR HANDLING CODE, it should behave the same
without that (error handling code) as well.

Regards,
Harish Sharma

Jul 29 '06 #12
sh**********@gmail.com wrote:
mlimber,

I tried compiling the same program with a later ver of MS C/C++
compiler, which is ...
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42
for 80x86

With this compiler the test program gives expected results. But the GCC
compiler that I am using is gcc version 3.3.1 (mingw special
20030804-1), and it still gives out garbage. And by the way I believe,
there is no garbage i/p in the test program and hence there is no
question of GIGO.
I used g++ 3.4.4 (cygming special) to build and run this program:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdlib>

using namespace std;

class MyException {};

template<class T>
T value(const string& s)
{
istringstream is(s);
T val;
if( !(is >val) || !(is >ws).eof() )
{
throw MyException();
}
return val;
}

int main()
{
cout << "atof(2.22507e-308) - "
<< atof("2.22507e-308") << '\n';
try
{
cout << "value<double>(2.22507e-308) ->"
<< value<double>("2.22507e-308");
}
catch( ... )
{
cout << "Caught exception.";
}
cout << endl;
}

It gives me the expected result. If it does not for you, then it is
likely a compiler/library problem, which you should ask about on
gnu.g++.help or similar.
Moreover, I don't think there is any need of
exception handling in the test code with the given valid input and I
don't understand how that extra piece of error checking will help. If
your compiler/lib gives you expected results with the given input, it
should behave the same without that as well.

Lastly I tried your changes with GCC and it generates exception and
that tells me that there is some definite issue in the related version
of c++ lib that it is using.
The exception handling is an alternate way of handling unexpected
errors to checking return values (cf.
http://www.parashift.com/c++-faq-lit...html#faq-17.1). In
this case, exceptions provide a way to indicate a failure without
having some sort of potentially invalid value (e.g., return FLOAT_MIN
on error or a std::pair<float,boolwhere the flag indicates validity)
being returned to the client, and the client can catch and handle such
an error at whatever level is appropriate. Anyway, the fact that you
get an exception seems to indicate that there was in fact an unexpected
error of some kind, so I think your claim that this sort of error
checking is unnecessary is self-defeating.

Cheers! --M

Jul 31 '06 #13
Anyway, the fact that you
get an exception seems to indicate that there was in fact an unexpected
error of some kind, so I think your claim that this sort of error
checking is unnecessary is self-defeating.
*self-defeating* ?

My comment on exception handling was not general and was specific to
the test code with the given *valid* input to the program.

Regards,
Harish Sharma

Aug 1 '06 #14
sh**********@gmail.com wrote:
I need a conversion function that converts values from string to a
particular type. For this I have a template function that looks like
this ...

template<class T>
T value(const string& s)
{
istringstream(s);
T val;
is >val;
return val;
}

Now for double type the lowest positive value is 2.22507-308 and I get
different answers when I use this function vs atof() function. I am not
getting the reason here. Interestingly, if I reduce the exponent value
from -308 to -307, I get similar results.
atof() causes undefined behaviour if the result isn't representable
as a double. Change to strtod() instead of atof(), and see if you
still get the same problem.

Aug 1 '06 #15

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by kaede | last post: by
9 posts views Thread by el_boricua | last post: by
4 posts views Thread by Matt | last post: by
3 posts views Thread by Herb Stevenson | last post: by
5 posts views Thread by Evyn | last post: by
reply views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.