\n
EDIT: I think I am being misunderstood. I want the output to be of dynamic length, not a fixed precision. I am familiar with setprecision. If you look at the java source for Double, it calculates the number of significant digits somehow, and I would really like to understand how it works and/or how feasible it is to replicate this easily in C++.
\n/*\n * FIRST IMPORTANT CONSTRUCTOR: DOUBLE\n */\npublic FloatingDecimal( double d )\n{\n long dBits = Double.doubleToLongBits( d );\n long fractBits;\n int binExp;\n int nSignificantBits;\n\n // discover and delete sign\n if ( (dBits&signMask) != 0 ){\n isNegative = true;\n dBits ^= signMask;\n } else {\n isNegative = false;\n }\n // Begin to unpack\n // Discover obvious special cases of NaN and Infinity.\n binExp = (int)( (dBits&expMask) >> expShift );\n fractBits = dBits&fractMask;\n if ( binExp == (int)(expMask>>expShift) ) {\n isExceptional = true;\n if ( fractBits == 0L ){\n digits = infinity;\n } else {\n digits = notANumber;\n isNegative = false; // NaN has no sign!\n }\n nDigits = digits.length;\n return;\n }\n isExceptional = false;\n // Finish unpacking\n // Normalize denormalized numbers.\n // Insert assumed high-order bit for normalized numbers.\n // Subtract exponent bias.\n if ( binExp == 0 ){\n if ( fractBits == 0L ){\n // not a denorm, just a 0!\n decExponent = 0;\n digits = zero;\n nDigits = 1;\n return;\n }\n while ( (fractBits&fractHOB) == 0L ){\n fractBits <<= 1;\n binExp -= 1;\n }\n nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.\n binExp += 1;\n } else {\n fractBits |= fractHOB;\n nSignificantBits = expShift+1;\n }\n binExp -= expBias;\n // call the routine that actually does all the hard work.\n dtoa( binExp, fractBits, nSignificantBits );\n}\n
\nAfter this function, it calls dtoa( binExp, fractBits, nSignificantBits );
which handles a bunch of cases - this is from OpenJDK6
For more clarity, an example:\nJava:
\ndouble test1 = 1.2593;\ndouble test2 = 0.004963;\ndouble test3 = 1.55558742563;\n \nSystem.out.println(test1);\nSystem.out.println(test2);\nSystem.out.println(test3);\n
\nOutput:
\n1.2593\n0.004963\n1.55558742563\n
\nC++:
\nstd::cout << test1 << "\\n";\nstd::cout << test2 << "\\n";\nstd::cout << test3 << "\\n";\n
\nOutput:
\n1.2593\n0.004963\n1.55559\n
\n","author":{"@type":"Person","name":"dave"},"upvoteCount":11,"answerCount":4,"acceptedAnswer":{"@type":"Answer","text":"I think you are talking about how to print the minimum number of floating point digits that allow you to read the exact same floating point number back. This paper is a good introduction to this tricky problem.
\n\nhttp://grouper.ieee.org/groups/754/email/pdfq3pavhBfih.pdf
\n\nThe dtoa function looks like David Gay's work, you can find the source here http://www.netlib.org/fp/dtoa.c (although this is C not Java).
\n\nGay also wrote a paper about his method. I don't have a link but it's referenced in the above paper so you can probably google it.
\n","author":{"@type":"Person","name":"jahhaj"},"upvoteCount":6}}}Reputation: 1637
When dealing with floating point values in Java, calling the toString()
method gives a printed value that has the correct number of floating point significant figures. However, in C++, printing a float via stringstream
will round the value after 5 or less digits. Is there a way to "pretty print" a float in C++ to the (assumed) correct number of significant figures?
EDIT: I think I am being misunderstood. I want the output to be of dynamic length, not a fixed precision. I am familiar with setprecision. If you look at the java source for Double, it calculates the number of significant digits somehow, and I would really like to understand how it works and/or how feasible it is to replicate this easily in C++.
/*
* FIRST IMPORTANT CONSTRUCTOR: DOUBLE
*/
public FloatingDecimal( double d )
{
long dBits = Double.doubleToLongBits( d );
long fractBits;
int binExp;
int nSignificantBits;
// discover and delete sign
if ( (dBits&signMask) != 0 ){
isNegative = true;
dBits ^= signMask;
} else {
isNegative = false;
}
// Begin to unpack
// Discover obvious special cases of NaN and Infinity.
binExp = (int)( (dBits&expMask) >> expShift );
fractBits = dBits&fractMask;
if ( binExp == (int)(expMask>>expShift) ) {
isExceptional = true;
if ( fractBits == 0L ){
digits = infinity;
} else {
digits = notANumber;
isNegative = false; // NaN has no sign!
}
nDigits = digits.length;
return;
}
isExceptional = false;
// Finish unpacking
// Normalize denormalized numbers.
// Insert assumed high-order bit for normalized numbers.
// Subtract exponent bias.
if ( binExp == 0 ){
if ( fractBits == 0L ){
// not a denorm, just a 0!
decExponent = 0;
digits = zero;
nDigits = 1;
return;
}
while ( (fractBits&fractHOB) == 0L ){
fractBits <<= 1;
binExp -= 1;
}
nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
binExp += 1;
} else {
fractBits |= fractHOB;
nSignificantBits = expShift+1;
}
binExp -= expBias;
// call the routine that actually does all the hard work.
dtoa( binExp, fractBits, nSignificantBits );
}
After this function, it calls dtoa( binExp, fractBits, nSignificantBits );
which handles a bunch of cases - this is from OpenJDK6
For more clarity, an example: Java:
double test1 = 1.2593;
double test2 = 0.004963;
double test3 = 1.55558742563;
System.out.println(test1);
System.out.println(test2);
System.out.println(test3);
Output:
1.2593
0.004963
1.55558742563
C++:
std::cout << test1 << "\n";
std::cout << test2 << "\n";
std::cout << test3 << "\n";
Output:
1.2593
0.004963
1.55559
Upvotes: 11
Views: 6803
Reputation: 55705
Is there a way to "pretty print" a float in C++ to the (assumed) correct number of significant figures?
Yes, you can do it with C++20 std::format
, for example:
double test1 = 1.2593;
double test2 = 0.004963;
double test3 = 1.55558742563;
std::cout << std::format("{}", test1) << "\n";
std::cout << std::format("{}", test2) << "\n";
std::cout << std::format("{}", test3) << "\n";
prints
1.2593
0.004963
1.55558742563
The default format will give you the shortest decimal representation with a round-trip guarantee like in Java.
Since this is a new feature and may not be supported by some standard libraries yet, you can use the {fmt} library, std::format
is based on. {fmt} also provides the print
function that makes this even easier and more efficient (godbolt):
fmt::print("{}", 1.2593);
Disclaimer: I'm the author of {fmt} and C++20 std::format
.
Upvotes: 2
Reputation: 16373
There is a utility called numeric_limits:
#include <limits>
...
int num10 = std::numeric_limits<double>::digits10;
int max_num10 = std::numeric_limits<double>::max_digits10;
Note that IEEE numbers are not represented exactly bydecimal digits. These are binary quantities. A more accurate number is the number of binary bits:
int bits = std::numeric_limits<double>::digits;
To pretty print all the significant digits use setprecision with this:
out.setprecision(std::numeric_limits<double>::digits10);
Upvotes: -1
Reputation: 3119
I think you are talking about how to print the minimum number of floating point digits that allow you to read the exact same floating point number back. This paper is a good introduction to this tricky problem.
http://grouper.ieee.org/groups/754/email/pdfq3pavhBfih.pdf
The dtoa function looks like David Gay's work, you can find the source here http://www.netlib.org/fp/dtoa.c (although this is C not Java).
Gay also wrote a paper about his method. I don't have a link but it's referenced in the above paper so you can probably google it.
Upvotes: 6
Reputation: 101
You can use the ios_base::precision technique where you can specify the number of digits you want
For example
#include <iostream>
using namespace std;
int main () {
double f = 3.14159;
cout.unsetf(ios::floatfield); // floatfield not set
cout.precision(5);
cout << f << endl;
cout.precision(10);
cout << f << endl;
cout.setf(ios::fixed,ios::floatfield); // floatfield set to fixed
cout << f << endl;
return 0;
The above code with output
3.1416
3.14159
3.1415900000
Upvotes: -1