Quando si gestiscono valori in virgola mobile in Java, la chiamata al metodo toString() fornisce un valore stampato con il numero corretto di cifre significative in virgola mobile. Tuttavia, in C++, la stampa di un float tramite stringstream arrotonda il valore dopo 5 o meno cifre. C'è un modo per "stampare bene" un float in C++ al numero corretto (presunto) di cifre significative?Come calcolare il numero di cifre decimali significative di un doppio C++?
EDIT: Penso di essere frainteso. Voglio che l'output sia di lunghezza dinamica, non una precisione fissa. Conosco la setprecision. Se guardi il sorgente Java per Double, calcola il numero di cifre significative in qualche modo, e mi piacerebbe davvero capire come funziona e/o quanto sia fattibile replicarlo facilmente 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);
}
Dopo questa funzione, si chiama dtoa(binExp, fractBits, nSignificantBits);
che gestisce una serie di casi - questo è da openjdk6
Per maggiore chiarezza, un esempio: 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);
uscita :
1.2593
0.004963
1.55558742563
C++:
std::cout << test1 << "\n";
std::cout << test2 << "\n";
std::cout << test3 << "\n";
uscita:
1.2593
0.004963
1.55559
Il metodo 'toString' non dà il "numero corretto" di figure significative; non ha modo di sapere quale delle figure sia significativa. I numeri in virgola mobile IEEE non rappresentano tali informazioni. –
Per riferimento, ecco un approccio Java comune a [* Customizing Formats *] (http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html). – trashgod
Java esegue una serie di calcoli sul doppio valore durante la stampa: non sono abbastanza esperto per capire cosa sta facendo. Vedi edit – dave