I am finding that atof is limited in the size of a string that it will parse.
Example:
float num = atof("49966.73");
cout << num;
shows 49966.7
num = atof("499966.73");
cout << num;
shows 499966
I need something that will parse the whole string accurately, to a floating point number, not just the first 6 characters.
Use std::setprecision and std::fixed from <iomanip> standard library, as mentioned in the comments, still, there will be conversion issues due to lack of precision of float types, for better results use double and std::stod for conversion:
float num = std::atof("499966.73");
std::cout << std::fixed << std::setprecision(2) << num;
double num = std::stod("499966.73");
std::cout << std::fixed << std::setprecision(2) << num;
The first prints 499966.72, the latter 499966.73.
Related
I am trying to convert a string to a double, however when i use stod() the double has lost some of it's decimal places.
Here is the relevant code :
cout << line3 << endl;
float temp = stod(line3);
cout << temp << endl;
For example, when line3 is "4.225308642", temp outputs as 4.22531. What is causing the shortening of the number and how can I fix it?
There are two aspects to consider here.
First, formating on a IOStream by default has a precision of 6 significant digits. That explains your result. You can increase the precision with the manipulator setprecision.
Then, float by itself has a limited precision of about 6 decimal digits as well. Although you can display more, they will be the result of displaying a binary float as decimal, not really an increase of the precision. You can get about 15 decimal digits of precision by using double.
So combining the two, the program
#include <iostream>
#include <string>
#include <iomanip>
int main() {
std::string line3 = "4.225308642";
std::cout << line3 << '\n';
float tempf = stof(line3);
double tempd = stod(line3);
std::cout << "default: float=" << tempf << ", double=" << tempd << '\n';
std::cout << std::setprecision(20);
std::cout << "precision(20): float=" << tempf << ", double=" << tempd << '\n';
}
has for result:
4.225308642
default: float=4.22531, double=4.22531
precision(20): float=4.2253084182739257812, double=4.2253086419999998924
Note again that the last digits result of displaying a binary format. There is a precision after which you can't expect a decimal representation matching the input, and 20 is greater than that. That aspect is explained in more details here.
In C++, I have some code like this:
float hits = 10.12;
float mins = 2.19;
std::ostringstream ss;
ss.precision(2);
ss << std::fixed << hits << "%\n"
<< std::fixed << mins << "%";
std::cout << ss.str();
Which is giving me this output:
10.12%
2.19%
Whereas, instead I would like the decimal places to align:
10.12%
2.19%
Is there a way to pad with spaces before the decimal to have a fixed width of space for two digits before the decimal place?
Use width to set the column size and then std::right to justify the output.
There are setw() and setprecision() to determine the output-width and the precision for floating-point-values. So you should be able to use it like
ss << setw(8) << hits << "%\n"; ...
Look here for reference.
I have this code:
double a = 7.456789;
cout.unsetf(ios::floatfield);
cout.precision(5);
cout << a;
and also this one:
double a = 798456.6;
cout.unsetf(ios::floatfield);
cout.precision(5);
cout << a;
the result of the first code is: 7.4568
Which is almost what I want (what I want to recieve is 7.4567)
the result of the second : 7.9846e+05
Which is not at all what I want (I want 798456.6)
I want to print the number till 4 numbers after the decimal point
How can I do that ?
By using unsetf(), you are telling cout to use its default formatting for floating-point values. Since you want an exact number of digits after the decimal, you should be using setf(fixed) or std::fixed instead, eg:
double a = ...;
std::cout.setf(std::fixed, ios::floatfield);
std::cout.precision(5);
std::cout << a;
.
double a = ...;
std::cout.precision(5);
std::cout << std::fixed << a;
double val = 0.1;
std::stringstream ss;
ss << val;
std::string strVal= ss.str();
In the Visual Studio debugger, val has the value 0.10000000000000001 (because 0.1 can't be represented).
When val is converted using stringstream, strVal is equal to "0.1". However, when using boost::lexical_cast, the resulting strVal is "0.10000000000000001".
Another example is the following:
double val = 12.12305000012;
Under visual studio val appears as 12.123050000119999, and using stringstream and default precision (6) it becomes 12.1231. I don't really understand why it is not 12.12305(...).
Is there a default precision, or does stringstream have a particular algorithm to convert a double value which can't be exactly represented?
Thanks.
You can change the floating-point precision of a stringstream as follows:
double num = 2.25149;
std::stringstream ss(stringstream::in | stringstream::out);
ss << std::setprecision(5) << num << endl;
ss << std::setprecision(4) << num << endl;
Output:
2.2515
2.251
Note how the numbers are also rounded when appropriate.
For anyone who gets "error: ‘setprecision’ is not a member of ‘std’" you must #include <iomanip> else setprecision(17) will not work!
There are two issues you have to consider. The first is the precision
parameter, which defaults to 6 (but which you can set to whatever you
like). The second is what this parameter means, and that depends on the
format option you are using: if you are using fixed or scientific
format, then it means the number of digits after the decimal (which in
turn has a different effect on what is usually meant by precision in the
two formats); if you are using the default precision, however (ss.setf(
std::ios_base::fmtflags(), std::ios_base::formatfield ), it means the
number of digits in the output, regardless of whether the output was
actually formatted using scientific or fixed notation. This explains
why your display is 12.1231, for example; you're using both the
default precision and the default formattting.
You might want to try the following with different values (and maybe
different precisions):
std::cout.setf( std::ios_base::fmtflags(), std::ios_base::floatfield );
std::cout << "default: " << value[i] << std::endl;
std::cout.setf( std::ios_base::fixed, std::ios_base::floatfield );
std::cout << "fixed: " << value[i] << std::endl;
std::cout.setf( std::ios_base::scientific, std::ios_base::floatfield );
std::cout << "scientific: " << value[i] << std::endl;
Seeing the actual output will probably be clearer than any detailed description:
default: 0.1
fixed: 0.100000
scientific: 1.000000e-01
The problem occurs at the stream insertion ss << 0.1; rather than at the conversion to string. If you want non-default precision you need to specify this prior to inserting the double:
ss << std::setprecision(17) << val;
On my computer, if I just use setprecision(16) I still get "0.1" rather than "0.10000000000000001". I need a (slightly bogus) precision of 17 to see that final 1.
Addendum
A better demonstration arises with a value of 1.0/3.0. With the default precision you get a string representation of "0.333333". This is not the string equivalent of a double precision 1/3. Using setprecision(16) makes the string "0.3333333333333333"; a precision of 17 yields "0.33333333333333331".
I have an issue regarding conversion from float to c++ string using ostringstream. Here is my line:
void doSomething(float t)
{
ostringstream stream;
stream << t;
cout << stream.str();
}
when t has value -0.89999 it is round off to -0.9, but when it's value is 0.0999 or lesser than this say 1.754e-7, it just prints without round off. what can be the solution for this.
You need to set the precision for ostringstream using precision
e.g
stream.precision(3);
stream<<fixed; // for fixed point notation
//cout.precision(3); // display only
stream << t;
cout<<stream.str();
If you want a particular number of significant figures displayed try using setprecision(n) where n is the number of significant figures you want.
#include <iomanip>
void doSomething(float t)
{
ostringstream stream;
stream << std::setprecision(4) << t;
cout << stream.str();
}
If you want fixed-point instead of scientific notation, use std::fixed:
stream << std::fixed << t;
Additionally you might want to set the precision as mentioned.
Use setprecision:
stream << setprecision(5) <<t ;
Now, your string stream.str() will be of the required precision.