I am having a application in which I have to process very large numbers. Application API gives me number then I had to convert it into the string and send to further processing.
Code receives number as - 1535625179.1619387
Then for conversion I have used -
char buffer[255];
sprintf(buffer, "%e", OverallVolume); //OverallVolume has the above value.
Now here buffer variable return 1.535625e+009 which is normalized as 1535625000.00
BUT my application shows value as 1.5356252e+09 which is normalized as 1535625200.00
So I want to ask what method I should be using to covert Double to String so that my resultant value will match to the value shown by application.
If I understand your question correctly, you want 7 digits to appear after the decimal point. To do that specify a precision as follows:
sprintf(buffer, "%.7e", OverallVolume); // buffer contains 1.5356252e+09
Live demo
Also, since this is tagged C++, here's a version using IO streams that prints the same result.
#include <ios>
#include <iomanip>
#include <iostream>
#include <sstream>
int main()
{
double OverallVolume = 1535625179.1619387;
std::ostringstream ss;
ss << std::scientific << std::setprecision(7) << OverallVolume;
std::cout << ss.str() << '\n'; // prints 1.5356252e+09
}
Live demo
Related
Have googled a lot about avoiding rounding errors but none of them are solving my case. Need to round off 9.99999975e-05 upto 8 or more precision.
Have tried using stringstream along with setprecision which is pretty much the standard way according to other answers on this site.
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
int main(void){
double val = 9.99999975e-05;
stringstream tmp;
tmp << setprecision(8) << fixed << val;
cout << tmp.str();
return 0;
}
Ideally I would like the result to be 0.00009999
But I am getting 0.00010000 , which I believe is occurring due to rounding off from farthest to most significant '9'.
Any idea how can I stop rounding at 8th precision ?
Need to round off 9.99999975e-05 upto 8 or more precision. (...)
I would like the result to be 0.00009999
Without other test cases I can only guess the OP's intent. So why not truncating the string resulting from the maximum output precision possible?
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <limits>
int main()
{
double val = 9.99999975e-05;
std::stringstream tmp;
tmp << std::setprecision(std::numeric_limits<double>::digits10 + 1)
<< std::fixed << val;
auto repr = tmp.str();
// Truncate the string
repr = repr.erase(repr.find('.') + 9);
std::cout << repr << '\n'; // --> 0.00009999
}
I'll also assume that the OP are already aware of What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Which platform are you using ? You can try using fesetround api in linux and _controlfp in windows.
I get Value 0.000099999998 on linux when rounding set to zero.
However, i will always recommend using a floating point library for such codes.
For the sake of completeness after going through How to truncate a floating point number after a certain number of decimal places (no rounding)? mentioned by #Arne above in comments, here's the changes that I made to above piece of code;
double val = 9.99999975e-05;
cout << setprecision(8) << fixed << trunc(100000000 * val) / 100000000;
return 0;
I've used setprecision(8), but when I count asin(1) it returns 0.017452406 (10 digits, not 8!) What can be done there?
In order to fix the problem with decimal digits you need to use std::fixed.
As explaned in C++ Reference
Sets the floatfield format flag for the str stream to fixed.
When floatfield is set to fixed, floating-point values are written using fixed-point notation: the value is represented with exactly as many digits in the decimal part as specified by the precision field (precision) and with no exponent part.
To answer your requirement from the comments: "I need to make number (both integer and decimal parts) to be displayed in max 8 digits." You could use an ostringstream.
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
int main(){
std::ostringstream ss; // declare your string stream
ss << std::setprecision(16); // set a high precision to avoid rounding
// Insert your float to the string stream
float f = 0.123456789;
ss << f;
// Get the string from the stream
std::string f_str = ss.str();
// Print
std::cout << f_str.substr(0, 8 + 1) << std::endl; // take 8 first digits
// Note the +1 here ^ (because of the dot)
return 0;
}
Output
0.1234567
This is a snippet of my code. I need some help in removing the error shown below.
#include <iostream>
#include <string>
#include <sstream>
int main()
{
char doubleStr[] = "5.2";
double d = 0.0;
std::stringstream stream (doubleStr);
stream >> d;
std::cout << d << std::endl;
std::cout << (d <= 5.2);
return 0;
}
This gives output:
5.200000000002
0
How to remove this precision error? Can I use std::setprecision() to solve the issue?
numeric_limits<double>::digits10 can be used to find the number of digits that are uniquely representable by a double.
I see you've tagged your question with Visual Studio. You can test this code on http://webcompiler.cloudapp.net/ to get Visual Studio's number of uniquely representable digits for a double:
#include <iostream>
#include <limits>
int main() { std::cout << std::numeric_limits<double>::digits10 << std::endl; }
This code will not output 2 it will output:
15
Which means that any double up to 14 decimal places will survive the round trip through a stringstream and still be equal to itself.
The above means that there is something you are not including in your example that is causing the round trip failure, or you are using non-standard source files that are not IEEE compliant. (For example I can do a live example on gcc that gives a contrary output to yours, and running the same code on Visual Studio disagrees with your output.)
Either way, for any uniquely representable double (like 5.2), you can ensure that round trip success through a stringstream by setting the precision. Precision is a sticky modifier, so you'll only need to set it once after stream construction. In your example you use stringstream stream so before you work with stream you'd need to set this modifier:
stream.precision(numeric_limits<double>::digits10 - 1);
You can use it like this in order to show the double number in the right way:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <limits>
int main()
{
char doubleStr[] = "5.2";
double d = 0.0;
std::stringstream stream (doubleStr);
stream >> d;
std::cout << std::setprecision(2)<< d << std::endl;
return 0;
}
http://cpp.sh/9lub
about comparing float point numbers you may look at this What is the most effective way for float and double comparison?
I need help on keeping the precision of a double. If I assign a literal to a double, the actual value was truncated.
int main() {
double x = 7.40200133400;
std::cout << x << "\n";
}
For the above code snippet, the output was 7.402
Is there a way to prevent this type of truncation? Or is there a way to calculate exactly how many floating points for a double? For example, number_of_decimal(x) would give 11, since the input is unknown at run-time so I can't use setprecision().
I think I should change my question to:
How to convert a double to a string without truncating the floating points. i.e.
#include <iostream>
#include <string>
#include <sstream>
template<typename T>
std::string type_to_string( T data ) {
std::ostringstream o;
o << data;
return o.str();
}
int main() {
double x = 7.40200;
std::cout << type_to_string( x ) << "\n";
}
The expected output should be 7.40200 but the actual result was 7.402. So how can I work around this problem? Any idea?
Due to the fact the float and double are internally stored in binary, the literal 7.40200133400 actually stands for the number 7.40200133400000037653398976544849574565887451171875
...so how much precision do you really want? :-)
#include <iomanip>
int main()
{
double x = 7.40200133400;
std::cout << std::setprecision(51) << x << "\n";
}
And yes, this program really prints 7.40200133400000037653398976544849574565887451171875!
You must use setiosflags(ios::fixed) and setprecision(x).
For example, cout << setiosflags(ios::fixed) << setprecision(4) << myNumber << endl;
Also, don't forget to #include <iomanip.h>.
std::cout << std::setprecision(8) << x;
Note that setprecision is persistent and all next floats you print will be printed with that precision, until you change it to a different value. If that's a problem and you want to work around that, you can use a proxy stringstream object:
std::stringstream s;
s << std::setprecision(8) << x;
std::cout << s.str();
For more info on iostream formatting, check out the Input/output manipulators section in cppreference.
Solution using Boost.Format:
#include <boost/format.hpp>
#include <iostream>
int main() {
double x = 7.40200133400;
std::cout << boost::format("%1$.16f") % x << "\n";
}
This outputs 7.4020013340000004.
Hope this helps!
The only answer to this that I've come up with is that there is no way to do this (as in calculate the decimal places) correctly! THE primary reason for this being that the representation of a number may not be what you expect, for example, 128.82, seems innocuous enough, however it's actual representation is 128.8199999999... how do you calculate the number of decimal places there??
Responding to your answer-edit: There is no way to do that. As soon as you assign a value to a double, any trailing zeroes are lost (to the compiler/computer, 0.402, 0.4020, and 0.40200 are the SAME NUMBER). The only way to retain trailing zeroes as you indicated is to store the values as strings (or do trickery where you keep track of the number of digits you care about and format it to exactly that length).
Let s make an analogous request: after initialising an integer with 001, you would want to print it with the leading zeroes. That formatting info was simply never stored.
For further understanding the double precision floating point storage, look at the IEEE 754 standard.
Doubles don't have decimal places. They have binary places. And binary places and decimal places are incommensurable (because log2(10) isn't an integer).
What you are asking for doesn't exist.
The second part of the question, about how to preserve trailing zeroes in a floating point value from value specification to output result, has no solution. A floating point value doesn't retain the original value specification. It seems this nonsensical part was added by an SO moderator.
Regarding the first and original part of the question, which I interpret as how to present all significant digits of 7.40200133400, i.e. with output like 7.402001334, you can just remove trailing zeroes from an output result that includes only trustworthy digits in the double value:
#include <assert.h> // assert
#include <limits> // std::(numeric_limits)
#include <string> // std::(string)
#include <sstream> // std::(ostringstream)
namespace my{
// Visual C++2017 doesn't support comma-separated list for `using`:
using std::fixed; using std::numeric_limits; using std::string;
using std::ostringstream;
auto max_fractional_digits_for_positive( double value )
-> int
{
int result = numeric_limits<double>::digits10 - 1;
while( value < 1 ) { ++result; value *= 10; }
return result;
}
auto string_from_positive( double const value )
-> string
{
ostringstream stream;
stream << fixed;
stream.precision( max_fractional_digits_for_positive( value ) );
stream << value;
string result = stream.str();
while( result.back() == '0' )
{
result.resize( result.size() - 1 );
}
return result;
}
auto string_from( double const value )
-> string
{
return (0?""
: value == 0? "0"
: value < 0? "-" + string_from_positive( -value )
: string_from_positive( value )
);
}
}
#include<iostream>
auto main()
-> int
{
using std::cout;
cout << my::string_from( 7.40200133400 ) << "\n";
cout << my::string_from( 0.00000000000740200133400 ) << "\n";
cout << my::string_from( 128.82 ) << "\n";
}
Output:
7.402001334
0.000000000007402001334
128.81999999999999
You might consider adding logic for rounding to avoid long sequences of 9's, like in the last result.
I need help on keeping the precision of a double. If I assign a literal to a double, the actual value was truncated.
int main() {
double x = 7.40200133400;
std::cout << x << "\n";
}
For the above code snippet, the output was 7.402
Is there a way to prevent this type of truncation? Or is there a way to calculate exactly how many floating points for a double? For example, number_of_decimal(x) would give 11, since the input is unknown at run-time so I can't use setprecision().
I think I should change my question to:
How to convert a double to a string without truncating the floating points. i.e.
#include <iostream>
#include <string>
#include <sstream>
template<typename T>
std::string type_to_string( T data ) {
std::ostringstream o;
o << data;
return o.str();
}
int main() {
double x = 7.40200;
std::cout << type_to_string( x ) << "\n";
}
The expected output should be 7.40200 but the actual result was 7.402. So how can I work around this problem? Any idea?
Due to the fact the float and double are internally stored in binary, the literal 7.40200133400 actually stands for the number 7.40200133400000037653398976544849574565887451171875
...so how much precision do you really want? :-)
#include <iomanip>
int main()
{
double x = 7.40200133400;
std::cout << std::setprecision(51) << x << "\n";
}
And yes, this program really prints 7.40200133400000037653398976544849574565887451171875!
You must use setiosflags(ios::fixed) and setprecision(x).
For example, cout << setiosflags(ios::fixed) << setprecision(4) << myNumber << endl;
Also, don't forget to #include <iomanip.h>.
std::cout << std::setprecision(8) << x;
Note that setprecision is persistent and all next floats you print will be printed with that precision, until you change it to a different value. If that's a problem and you want to work around that, you can use a proxy stringstream object:
std::stringstream s;
s << std::setprecision(8) << x;
std::cout << s.str();
For more info on iostream formatting, check out the Input/output manipulators section in cppreference.
Solution using Boost.Format:
#include <boost/format.hpp>
#include <iostream>
int main() {
double x = 7.40200133400;
std::cout << boost::format("%1$.16f") % x << "\n";
}
This outputs 7.4020013340000004.
Hope this helps!
The only answer to this that I've come up with is that there is no way to do this (as in calculate the decimal places) correctly! THE primary reason for this being that the representation of a number may not be what you expect, for example, 128.82, seems innocuous enough, however it's actual representation is 128.8199999999... how do you calculate the number of decimal places there??
Responding to your answer-edit: There is no way to do that. As soon as you assign a value to a double, any trailing zeroes are lost (to the compiler/computer, 0.402, 0.4020, and 0.40200 are the SAME NUMBER). The only way to retain trailing zeroes as you indicated is to store the values as strings (or do trickery where you keep track of the number of digits you care about and format it to exactly that length).
Let s make an analogous request: after initialising an integer with 001, you would want to print it with the leading zeroes. That formatting info was simply never stored.
For further understanding the double precision floating point storage, look at the IEEE 754 standard.
Doubles don't have decimal places. They have binary places. And binary places and decimal places are incommensurable (because log2(10) isn't an integer).
What you are asking for doesn't exist.
The second part of the question, about how to preserve trailing zeroes in a floating point value from value specification to output result, has no solution. A floating point value doesn't retain the original value specification. It seems this nonsensical part was added by an SO moderator.
Regarding the first and original part of the question, which I interpret as how to present all significant digits of 7.40200133400, i.e. with output like 7.402001334, you can just remove trailing zeroes from an output result that includes only trustworthy digits in the double value:
#include <assert.h> // assert
#include <limits> // std::(numeric_limits)
#include <string> // std::(string)
#include <sstream> // std::(ostringstream)
namespace my{
// Visual C++2017 doesn't support comma-separated list for `using`:
using std::fixed; using std::numeric_limits; using std::string;
using std::ostringstream;
auto max_fractional_digits_for_positive( double value )
-> int
{
int result = numeric_limits<double>::digits10 - 1;
while( value < 1 ) { ++result; value *= 10; }
return result;
}
auto string_from_positive( double const value )
-> string
{
ostringstream stream;
stream << fixed;
stream.precision( max_fractional_digits_for_positive( value ) );
stream << value;
string result = stream.str();
while( result.back() == '0' )
{
result.resize( result.size() - 1 );
}
return result;
}
auto string_from( double const value )
-> string
{
return (0?""
: value == 0? "0"
: value < 0? "-" + string_from_positive( -value )
: string_from_positive( value )
);
}
}
#include<iostream>
auto main()
-> int
{
using std::cout;
cout << my::string_from( 7.40200133400 ) << "\n";
cout << my::string_from( 0.00000000000740200133400 ) << "\n";
cout << my::string_from( 128.82 ) << "\n";
}
Output:
7.402001334
0.000000000007402001334
128.81999999999999
You might consider adding logic for rounding to avoid long sequences of 9's, like in the last result.