Come posso stampare un valore doppio con la massima precisione usando cout?
-
23-08-2019 - |
Domanda
Quindi ho ottenuto la risposta al mio ultima domanda (Non so perché non ci ho pensato).Stavo stampando un double
utilizzando cout
è stato arrotondato quando non me lo aspettavo.Come posso fare cout
stampa a double
utilizzando la massima precisione?
Soluzione
È possibile impostare la precisione direttamente sul std::cout
e utilizzare il std::fixed
di formato.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
È possibile #include <limits>
per ottenere la massima precisione di un galleggiante o doppia.
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
Altri suggerimenti
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
Ecco quello che vorrei utilizzare:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
In sostanza il pacchetto limiti ha dei tratti per tutta la configurazione in tipi.
Uno dei tratti per i numeri in virgola mobile (float / double / long double) è l'attributo digits10. Questo definisce la precisione (ho dimenticato la terminologia esatta) di un numero decimale in base 10.
See: http://www.cplusplus.com/reference/std/ limiti / numeric_limits.html
Per informazioni dettagliate su altri attributi.
Il modo iostreams è una specie di goffo. Io preferisco usare boost::lexical_cast
perché calcola la giusta precisione per me. E è veloce , anche.
#include <string>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
using std::string;
double d = 3.14159265358979;
cout << "Pi: " << lexical_cast<string>(d) << endl;
Output:
Pi: 3,14159265358979
Ecco come visualizzare una doppia con precisione completa:
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
Questa mostra:
100,0000000000005
max_digits10 è il numero di cifre che sono necessari per rappresentare univocamente tutti i valori doppi distinti. max_digits10 rappresenta il numero di cifre prima e dopo il punto decimale.
Non utilizzare set_precision (max_digits10) con std :: fisso.
Su notazione fissa, set_precision () imposta il numero di cifre solo dopo il punto decimale. Ciò è corretto come max_digits10 rappresenta il numero di cifre prima e dopo il punto decimale.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
Questa mostra risultato errato:
100,00000000000049738
Nota: i file header necessari
#include <iomanip>
#include <limits>
Con precisione piena, suppongo che significa precisione sufficiente per mostrare la migliore approssimazione al valore previsto, ma va sottolineato che è memorizzato double
utilizzando la rappresentazione base 2 e la base 2 non può rappresentare qualcosa di così banale come 1.1
esattamente. L'unico modo per ottenere il pieno intero precisione dell'effettiva doppia (con NO errore inerente) è quello di stampare i bit binari (o nybbles esadecimali). Un modo di fare che sta scrivendo la double
ad un union
e poi stampare il valore intero dei bit.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
Questo vi darà il 100% di precisione accurata del doppio ... ed essere assolutamente illeggibile perché gli esseri umani non possono leggere IEEE formato doppio! Wikipedia ha una buona scrittura su come interpretare i bit binari.
In più recente C ++, si può fare
std::cout << std::hexfloat << 1.1;
Come faccio a stampare un
double
valore con la massima precisione utilizzando cout?
Utilizzo hexfloat
O
utilizzo scientific
e impostare la precisione
std::cout.precision(std::numeric_limits<double>::max_digits10 - 1);
std::cout << std::scientific << 1.0/7.0 << '\n';
// C++11 Typical output
1.4285714285714285e-01
Troppe risposte riguardano solo una tra 1) base 2) layout fisso/scientifico o 3) precisione.Troppe risposte con precisione non fornire il valore corretto necessario.Da qui questa risposta ad una vecchia domanda.
- Quale base?
UN double
è certamente codificato utilizzando la base 2.Un approccio diretto con C++11 consiste nel stampare utilizzando std::hexfloat
.
Se un output non decimale è accettabile, abbiamo finito.
std::cout << "hexfloat: " << std::hexfloat << exp (-100) << '\n';
std::cout << "hexfloat: " << std::hexfloat << exp (+100) << '\n';
// output
hexfloat: 0x1.a8c1f14e2af5dp-145
hexfloat: 0x1.3494a9b171bf5p+144
- Altrimenti:
fixed
Oscientific
?
UN double
è un virgola mobile tipo, no Punto fisso.
Fare non utilizzo std::fixed
poiché non riesce a stampare in piccolo double
come tutt'altro 0.000...000
.Per grandi double
, stampa molte cifre, forse centinaia di discutibile informatività.
std::cout << "std::fixed: " << std::fixed << exp (-100) << '\n';
std::cout << "std::fixed: " << std::fixed << exp (+100) << '\n';
// output
std::fixed: 0.000000
std::fixed: 26881171418161356094253400435962903554686976.000000
Per stampare con la massima precisione, utilizzare prima std::scientific
che "scriverà valori in virgola mobile in notazione scientifica".Si noti che il valore predefinito di 6 cifre dopo il punto decimale, una quantità insufficiente, viene gestito nel punto successivo.
std::cout << "std::scientific: " << std::scientific << exp (-100) << '\n';
std::cout << "std::scientific: " << std::scientific << exp (+100) << '\n';
// output
std::scientific: 3.720076e-44
std::scientific: 2.688117e+43
- Quanta precisione (quante cifre totali)?
UN double
codificato utilizzando la base binaria 2 codifica la stessa precisione tra varie potenze di 2.Questo è spesso 53 bit.
[1.0...2.0) ce ne sono 253 diverso double
,
[2.0...4.0) ce ne sono 253 diverso double
,
[4.0...8.0) ce ne sono 253 diverso double
,
[8.0...10.0) ci sono 2/8 * 253 diverso double
.
Tuttavia, se il codice viene stampato in formato decimale con N
cifre significative, il numero di combinazioni [1.0...10.0) è 9/10 * 10N.
Qualunque cosa N
(precisione), non ci sarà una mappatura uno a uno tra double
e testo decimale. Se un fisso N
viene scelto, a volte sarà leggermente più o meno di quanto realmente necessario per certo double
valori.Potremmo sbagliare su troppo pochi (a)
sotto) o troppi (b)
sotto).
3 candidati N
:
a) Utilizzare un N
quindi quando si converte da testo-double
-text arriviamo allo stesso testo per tutti double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
b) Utilizzare un N
quindi durante la conversione da double
-testo-double
arriviamo allo stesso double
per tutti double
.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
Quando max_digits10
non è disponibile, tieni presente che a causa degli attributi base 2 e base 10, digits10 + 2 <= max_digits10 <= digits10 + 3
, possiamo usare digits10 + 3
per garantire che vengano stampate abbastanza cifre decimali.
c) Utilizzare un N
che varia con il valore.
Questo può essere utile quando il codice vuole visualizzare un testo minimo (N == 1
) o il esatto valore di a double
(N == 1000-ish
in caso di denorm_min
).Tuttavia, poiché questo è un "lavoro" e probabilmente non l'obiettivo dell'OP, verrà messo da parte.
Di solito è b) che viene utilizzato per "stampare a double
valore con la massima precisione".Alcune applicazioni potrebbero preferire a) all'errore di non fornire troppe informazioni.
Con .scientific
, .precision()
imposta il numero di cifre da stampare dopo il punto decimale, quindi 1 + .precision()
le cifre vengono stampate.Esigenze del codice max_digits10
cifre totali così .precision()
si chiama con a max_digits10 - 1
.
typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10 - 1);
std::cout << std::scientific << exp (-100) << '\n';
std::cout << std::scientific << exp (+100) << '\n';
// Typical output
3.7200759760208361e-44
2.6881171418161356e+43
printf("%.12f", M_PI);
%. 12f mezzi virgola mobile, con precisione di 12 cifre.
cout è un oggetto che ha un sacco di metodi che è possibile chiamare per modificare la precisione e la formattazione di roba stampata.
C'è un setprecision (...) il funzionamento, ma è anche possibile impostare altre cose come larghezza di stampa, ecc.
Look up cout riferimento del vostro IDE.
La maggior parte portabile ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;
Con ostream :: precisione (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
produrrà
3.141592653589793, 2.718281828459045
Perché avete da dire "+1" Non ho idea, ma la cifra più si ottiene fuori di esso è corretto.