Podczas przetwarzania wartości zmiennoprzecinkowych w Javie, wywołanie metody toString() daje wydrukowaną wartość, która ma prawidłową liczbę znaczących liczb zmiennoprzecinkowych. Jednak w C++, drukowanie float za pośrednictwem stringstream będzie zaokrąglało wartość po 5 lub mniej cyfrach. Czy istnieje sposób na "ładny wydruk" float w C++ do (zakładanej) poprawnej liczby znaczących liczb?Jak obliczyć liczbę znaczących cyfr dziesiętnych C++ double?
EDYCJA: Myślę, że jestem źle rozumiany. Chcę, aby wyjście miało dynamiczną długość, a nie stałą precyzję. Jestem zaznajomiony z setprecision. Jeśli spojrzysz na źródło java dla Double, to w jakiś sposób oblicza ono liczbę cyfr znaczących i naprawdę chciałbym zrozumieć, jak to działa i/lub jak łatwo jest to replikować w 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);
}
Po tej funkcji, wywołuje dtoa(binExp, fractBits, nSignificantBits);
który obsługuje kilka przypadków - to z OpenJDK6
Dla większej jasności, przykład: 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";
wyjściowa:
1.2593
0.004963
1.55559
Opcja 'metoda toString' nie daje„prawidłowy numer”z znaczące liczby; nie ma możliwości sprawdzenia, które z danych są znaczące. Liczby zmiennoprzecinkowe IEEE nie reprezentują tych informacji. –
Dla odniesienia, tutaj jest wspólne podejście Java do [* Customizing Formats *] (http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html). – trashgod
Java robi serię obliczeń na podwójnej wartości podczas drukowania - ja po prostu nie mam wystarczającej wiedzy, aby zrozumieć, co robi. Zobacz redakcję – dave