Need help converting a string to a float...

H

Hank Stalica

I'm having this weird problem where my code does the following
conversion from string to float:

27000000.0 -> 27000000.00
2973999.99 -> 29740000.00
2989999.13 -> 2989999.25

The number on the left is the string I get after tokenizing a bigger
string. The number on the right is the number I get after the conversion.

I've tried two different ways of converting, one way the older C way
using atof, and another more C++ way. Either way, I get the same
result. Can anyone shed some light on this for me?

Here's the code:

string token;
string tokens[14];
stringstream iss;
getline(fin,bfr);
while (getline(fin, bfr))
{
iss << bfr;
i = 0;
while (getline(iss, token, ','))
{
tokens[i++] = token;
}

std::istringstream b(tokens[0]);
b >> price;

//price = atof(tokens[0].c_str());
 
S

SpreadTooThin

I'm having this weird problem where my code does the following
conversion from string to float:

27000000.0 -> 27000000.00
2973999.99 -> 29740000.00
2989999.13 -> 2989999.25

The number on the left is the string I get after tokenizing a bigger
string. The number on the right is the number I get after the conversion.

I've tried two different ways of converting, one way the older C way
using atof, and another more C++ way. Either way, I get the same
result. Can anyone shed some light on this for me?

Here's the code:

string token;
string tokens[14];
stringstream iss;
getline(fin,bfr);
while (getline(fin, bfr))
{
iss << bfr;
i = 0;
while (getline(iss, token, ','))
{
tokens[i++] = token;
}

std::istringstream b(tokens[0]);
b >> price;

//price = atof(tokens[0].c_str());

I don't think conversion is your problem, I think its your method of
outputting your numbers that is causing rounding and confusion...
JMO.
 
H

Hank Stalica

Could be.

Here's code I used to display the numbers side by side:

printf("%s %10.2f\n",tokens[0].c_str(), price);
I'm having this weird problem where my code does the following
conversion from string to float:

27000000.0 -> 27000000.00
2973999.99 -> 29740000.00
2989999.13 -> 2989999.25

The number on the left is the string I get after tokenizing a bigger
string. The number on the right is the number I get after the conversion.

I've tried two different ways of converting, one way the older C way
using atof, and another more C++ way. Either way, I get the same
result. Can anyone shed some light on this for me?

Here's the code:

string token;
string tokens[14];
stringstream iss;
getline(fin,bfr);
while (getline(fin, bfr))
{
iss << bfr;
i = 0;
while (getline(iss, token, ','))
{
tokens[i++] = token;
}

std::istringstream b(tokens[0]);
b >> price;

//price = atof(tokens[0].c_str());

I don't think conversion is your problem, I think its your method of
outputting your numbers that is causing rounding and confusion...
JMO.
 
H

Hank Stalica

I used the following code to verify if it was display issue or an actual
conversion issue:

if (price == 2989999.13)
cout << "Match" << endl;

And match was not displayed, so it looks like the conversion is getting
screwed up somehow.
 
R

Robert Bauck Hamar

Hank said:
I'm having this weird problem where my code does the following
conversion from string to float:

27000000.0 -> 27000000.00
2973999.99 -> 29740000.00

Is this correct, or is it an extra 0?
2989999.13 -> 2989999.25

This sounds reasonable. If you know how a float looks like in your memory,
you'd expect this too.
The number on the left is the string I get after tokenizing a bigger
string. The number on the right is the number I get after the conversion.

I've tried two different ways of converting, one way the older C way
using atof, and another more C++ way. Either way, I get the same
result. Can anyone shed some light on this for me?

A float can't just store any number you put in. A float has a limited number
of precise digits. What you see is rounding errors.

#include <iostream>
#include <limits>

int main() {
std::cout << std::numeric_limits<float>::digits10 << "\n";
}

On my machine, this program outputs the number 6, indicating that a float
can store six decimal digits precisely. Your numbers have (except for the
first) more than six decimal digits. The indication is often a little low,
because computers don't use the decimal system.
Here's the code:

string token;
string tokens[14];
stringstream iss;
getline(fin,bfr);
while (getline(fin, bfr))
{
iss << bfr;
i = 0;
while (getline(iss, token, ','))
{
tokens[i++] = token;
}

std::istringstream b(tokens[0]);
b >> price;

//price = atof(tokens[0].c_str());

Don't expect floats or doubles to be accurate. And following: Never use
floats or doubles for prices.
 
H

Hank Stalica

Did a little bit of unit testing with the following code and got the
same result:

#include <iostream>
using std::cout;
using std::cin;

int main()
{
char s1[] = "2989999.13";
float f = atof(s1);
printf("%12.2f",f);

if (f == 2989999.13)
cout << "Matches";

return 0;
}

It's converting 2989999.13 to 2989999.25.
What's going on?
 
H

Hank Stalica

Ok, that makes sense.
So I should store the value as two ints? One for the whole number and
one for the fractional amount?
Hank said:
I'm having this weird problem where my code does the following
conversion from string to float:

27000000.0 -> 27000000.00
2973999.99 -> 29740000.00

Is this correct, or is it an extra 0?
2989999.13 -> 2989999.25

This sounds reasonable. If you know how a float looks like in your memory,
you'd expect this too.
The number on the left is the string I get after tokenizing a bigger
string. The number on the right is the number I get after the conversion.

I've tried two different ways of converting, one way the older C way
using atof, and another more C++ way. Either way, I get the same
result. Can anyone shed some light on this for me?

A float can't just store any number you put in. A float has a limited number
of precise digits. What you see is rounding errors.

#include <iostream>
#include <limits>

int main() {
std::cout << std::numeric_limits<float>::digits10 << "\n";
}

On my machine, this program outputs the number 6, indicating that a float
can store six decimal digits precisely. Your numbers have (except for the
first) more than six decimal digits. The indication is often a little low,
because computers don't use the decimal system.
Here's the code:

string token;
string tokens[14];
stringstream iss;
getline(fin,bfr);
while (getline(fin, bfr))
{
iss << bfr;
i = 0;
while (getline(iss, token, ','))
{
tokens[i++] = token;
}

std::istringstream b(tokens[0]);
b >> price;

//price = atof(tokens[0].c_str());

Don't expect floats or doubles to be accurate. And following: Never use
floats or doubles for prices.
 
R

Robert Bauck Hamar

Hank said:
Ok, that makes sense.
So I should store the value as two ints? One for the whole number and
one for the fractional amount?

Depends on what you need. If the fractional part is always a fixed number of
integers, you only need one integer. Just place the decimal separator when
printing and check it on input. Before you pick that solution, you should
assert that integers are big enough for your task. If not, you could use a
library. GMP might suit your needs <URL:http://gmplib.org/>

By the way: When following up, try to insert your text below the relevant
parts in the previous post. Then delete unrelevant parts.
 
M

Marcus Kwok

Hank,
Please don't top-post in this newsgroup. Your responses belong
interspersed with appropriately trimmed quotes. I have fixed it below.

Hank Stalica said:
Hank said:
I'm having this weird problem where my code does the following
conversion from string to float:

27000000.0 -> 27000000.00
2973999.99 -> 29740000.00
2989999.13 -> 2989999.25

The number on the left is the string I get after tokenizing a bigger
string. The number on the right is the number I get after the conversion.

Did a little bit of unit testing with the following code and got the
same result:
[code snipped]

It's converting 2989999.13 to 2989999.25.
What's going on?

See this entry in the FAQ (and also the surrounding ones):

[29.16] Why is floating point so inaccurate? Why doesn't this print 0.43?
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.16

Also, you should read this paper by David Goldberg when you have the
time (links given at the end of FAQ #29.17):

What Every Computer Scientist Should Know About Floating-Point Arithmetic
 
H

Hank Stalica

Thanks for the help, everyone and my apologies for top posting.

I decided to split the float up into two integers and it seems to be
working.

Best Regards,
--Hank Stalica
 

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

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top