If I have a double string which is equal to "123.546123" and convert it to a double with atof, I get only 123.546. What can I do to fix this?
Here is my code:
#include <iostream>
int main(){
std::string a = "123.546123";
double b = atof(a.c_str());
std::cout << a << std::endl;
std::cout << b << std::endl;
return EXIT_SUCCESS;
}
std::cout prints floating-point values with a precision of 6 by default. To increase that precision, use std::setprecision from <iomanip>, e.g.:
std::cout << std::setprecision(9) << b << std::endl;
Related
I am trying to solve the relatively simple problem of being able to write a double to a file and then to read the file into a double again. Based on this answer I decided to use the human readable format.
I have successfully circumvented the problems some compilers have with nan and [-]infinity according to this question. With finite numbers I use the std::stod function to convert the string representation of a number into the number itself. But from time to time the parsing fails with numbers close to zero, such as in the following example:
#include <cmath>
#include <iostream>
#include <sstream>
#include <limits>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
std::stringstream stream;
stream.precision(maxPrecision);
stream << small;
std::cout << "serialized: " << stream.str() << std::endl;
double out = std::stod(stream.str());
std::cout << "de-serialized: " << out << std::endl;
return 0;
}
On my machine the result is:
serialized: 9.2263152681638151025201733115952403273156653201666065e-318
terminate called after throwing an instance of 'std::out_of_range'
what(): stod
The program has unexpectedly finished.
That is, the number is too close to zero to be properly parsed. At first I thougth that the problem is that this number is denormal, but this doesn't seem to be the case, since the mantissa starts with a 9 and not a 0.
Qt on the other hand has no problems with this number:
#include <cmath>
#include <limits>
#include <QString>
#include <QTextStream>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
QString string = QString::number(small, 'g', maxPrecision);
QTextStream stream(stdout);
stream.setRealNumberPrecision(maxPrecision);
stream << "serialized: " << string << '\n';
bool ok;
double out = string.toDouble(&ok);
stream << "de-serialized: " << out << '\n' << (ok?"ok":"not ok") << '\n';
return 0;
}
Outputs:
serialized: 9.2263152681638151025201733115952403273156653201666065e-318
de-serialized: 9.2263152681638151025201733115952403273156653201666065e-318
ok
Summary:
Is this a bug in the gcc implementation of standard library?
Can I circumvent this elegantly?
Should I just use Qt?
Answering question #2:
This is probably my "C-way" kind of thinking, but you could copy the double into a uint64_t (mem-copying, not type-casting), serialize the uint64_t instead, and do the opposite on de-serialization.
Here is an example (without even having to copy from double into uint64_t and vice-versa):
uint64_t* pi = (uint64_t*)&small;
stringstream stream;
stream.precision(maxPrecision);
stream << *pi;
cout << "serialized: " << stream.str() << endl;
uint64_t out = stoull(stream.str());
double* pf = (double*)&out;
cout << "de-serialized: " << *pf << endl;
Please note that in order to avoid breaking strict-aliasing rule, you actually do need to copy it first, because the standard does not impose the allocation of double and uint64_t to the same address-alignment:
uint64_t ismall;
memcpy((void*)&ismall,(void*)&small,sizeof(small));
stringstream stream;
stream.precision(maxPrecision);
stream << ismall;
cout << "serialized: " << stream.str() << endl;
ismall = stoull(stream.str());
double fsmall;
memcpy((void*)&fsmall,(void*)&ismall,sizeof(small));
cout << "de-serialized: " << fsmall << endl;
If you're open to other recording methods you can use frexp:
#include <cmath>
#include <iostream>
#include <sstream>
#include <limits>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
std::stringstream stream;
stream.precision(maxPrecision);
int exp;
double x = frexp(small, &exp);
//std::cout << x << " * 2 ^ " << exp << std::endl;
stream << x << " * 2 ^ " << exp;
int outexp;
double outx;
stream.seekg(0);
stream >> outx;
stream.ignore(7); // >> " * 2 ^ "
stream >> outexp;
//std::cout << outx << " * 2 ^ " << outexp << std::endl;
std::cout << small << std::endl << outx * pow(2, outexp) << std::endl;
return 0;
}
This question already has answers here:
How to output with 3 digits after the decimal point with C++ stream?
(5 answers)
Closed 9 years ago.
In C language we can write like this;
printf("%.2f", number);
How can I do that in C++?
std::cout << "The number is " << number;
You need to use the iomanip stuff, such as with:
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589;
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
return 0;
}
which outputs:
3.14
If you want to localise the effects of your changes (both fixed and setprecision change the stream permanently), you can save the flags and precision before hand and restore them afterwards:
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589;
std::cout << pi << '\n';
// Save flags/precision.
std::ios_base::fmtflags oldflags = std::cout.flags();
std::streamsize oldprecision = std::cout.precision();
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
std::cout << pi << '\n';
// Restore flags/precision.
std::cout.flags (oldflags);
std::cout.precision (oldprecision);
std::cout << pi << '\n';
return 0;
}
The output of that is:
3.14159
3.14
3.14
3.14159
showing that the previous behaviour is being restored.
I was about to ask this question, and found a few more to ask.
How (according to the top answer) would I then proceed to only display this precision for a single call to cout, and then disable it thereafter?
Say I want to show precision for the first three calls, but not the last:
(I named a variable with the same name as the "fixed" format specifier in order to experiment)
#include <iostream>
int main(){
using namespace std;
int spam = 5;
double flak = 5.0;
double result = spam * flak;
double fixed = 42;
cout.precision(1);
cout << std::fixed << spam + flak << endl;
cout << result << endl;
cout << flak << endl;
cout << fixed;
return 0;
}
You can invoke the precision function again to re-apply it like so:
int main(){
using namespace std;
int spam = 5;
double flak = 5.0;
double result = spam * flak;
double fixed = 42;
cout.precision(1);
cout << std::fixed << spam + flak << endl;
cout << result << endl;
cout << flak << endl;
cout.precision(3);
cout << fixed;
return 0;
}
Another way to do it is to use the <iomanip> header to use the std::setprecision() function and passing it to std::cout, so it would be similar to doing this:
#include <iomanip>
#include <iostream>
int main() {
int spam = 5;
double flak = 5.0;
double result = spam * flak;
double fixed = 42;
std::cout << std::fixed << spam + flak << std::endl;
std::cout << std::setprecision(1) << result << '\n' << flak << std::endl;
std::cout << std::setprecision(0) << fixed;
return 0;
}
Not sure what you want. But C++ provides some ways to control the state of stream.
std::streamsize prec = cout.precision(); // store current precision setting
// some print here
std::cout.precision(prec) // Roll-back
One (ugly) way would be to cast it to int before the cout if you dont want to see the decimal places.
Something like (C style - still ok for primitive types)
cout << (int)flak << endl;
or ( C++ style - recommended, especially for non primitive types like classes)
cout << static_cast<int>(flak) << endl;
This will only change what cout sees, not the variable itself.
Given a variable of float type, how to output it with 3 digits after the decimal point, using iostream in C++?
Use setf and precision.
#include <iostream>
using namespace std;
int main () {
double f = 3.14159;
cout.setf(ios::fixed,ios::floatfield);
cout.precision(3);
cout << f << endl;
return 0;
}
This prints 3.142
This one does show "13.142"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
double f = 13.14159;
cout << fixed;
cout << setprecision(3) << f << endl;
return 0;
}
You can get fixed number of fractional digits (and many other things) by using the iomanip header. For example:
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589;
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
return 0;
}
will output:
3.14
Note that both fixed and setprecision change the stream permanently so, if you want to localise the effects, you can save the information beforehand and restore it afterwards:
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589;
std::cout << pi << '\n';
// Save flags/precision.
std::ios_base::fmtflags oldflags = std::cout.flags();
std::streamsize oldprecision = std::cout.precision();
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
std::cout << pi << '\n';
// Restore flags/precision.
std::cout.flags (oldflags);
std::cout.precision (oldprecision);
std::cout << pi << '\n';
return 0;
}
The output of that is:
3.14159
3.14
3.14
3.14159
If you want to print numbers with precision of 3 digits after decimal, just add the following thing before printing the number cout << std::setprecision(3) << desired_number. Don't forget to add #include <iomanip> in your code.
In general, precision is the maximum number of digits displayed. The manipulator fixed will set up the output stream for displaying values in fixed format. In fixed the precision is the number of digits after the decimal point. The setprecision allows setting the precision used for displaying floating-point values, it takes an integer argument.
cout << fixed;
cout << setprecision(3) << f << endl;
You may unset fixed using cout.unsetf(ios::fixed)
I am calculating square root of 2147483647 by sqrt function.and the result must be a float value 46340.95 but my code returns the value 46341.
Can anyone tell me where is the problem?
i am using code :
double x=2147483647.0;
double y=sqrt(x);
cout<< y;
I get that same result. But, if I inject a setprecision, I get the right value:
#include <iostream>
#include <iomanip>
#include <cmath>
int main (void) {
double x=2147483647.0;
double y=sqrt(x);
std::cout << std::setprecision(10) << y << std::endl;
return 0;
}
gives me:
46340.95
In fact, if you use the folowing code:
#include <iostream>
#include <iomanip>
#include <cmath>
int main (void) {
double x=2147483647.0;
double y=sqrt(x);
std::cout << y << std::endl;
std::cout << std::setprecision(0) << std::fixed << y << std::endl;
std::cout << std::setprecision(1) << std::fixed << y << std::endl;
std::cout << std::setprecision(2) << std::fixed << y << std::endl;
std::cout << std::setprecision(3) << std::fixed << y << std::endl;
return 0;
}
you get:
46341
46341
46341.0
46340.95
46340.950
So it appears that the default setting (at least for my environment) is a precision of zero.
If you want a specific format, I suggest you explicitly request it.
The default precision for cout is not sufficient to show the fractional part of your result. Your result is 46340.95, which rounded to six digits of precision is 43641.0, and is displayed as 43641 by cout. To show more precision, set the precision of cout first:
double x=2147483647.0;
double y=sqrt(x);
cout.precision(9);
cout<< y;
On my system this shows a result of 46340.95.
This trivial code yields 46340.9:
#include <cmath>
#include <iostream>
int main()
{
float x = std::sqrt(2147483647);
std::cout << x << std::endl;
return 0;
}
What does your code look like?
(Just for the record: tested using GCC (g++) 4.5.2 on MacOS X 10.6.6.)