Comment puis-je imprimer une valeur double avec toute la précision en utilisant Cout?
-
23-08-2019 - |
Question
J'ai obtenu la réponse à ma dernière question (I ne sais pas pourquoi je ne pensais pas que). Je l'impression d'un double
en utilisant cout
qui a obtenu arrondi quand je ne m'y attendais pas. Comment puis-je faire imprimer cout
une double
utilisant une précision complète?
La solution
Vous pouvez définir la précision directement sur std::cout
et utiliser le std::fixed
spécificateur de format.
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
Vous pouvez #include <limits>
pour obtenir la précision maximale d'un flotteur ou double.
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
Autres conseils
Utilisez std::setprecision
:
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
Voici ce que j'utiliser:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
Fondamentalement, le paquet a des traits limites pour tous les types de construction.
L'un des traits pour les nombres à virgule flottante (float / double / long double) est l'attribut digits10. Ceci définit la précision (j'oublie la terminologie exacte) d'un nombre à virgule flottante en base 10.
Voir: http://www.cplusplus.com/reference/std/ limites / numeric_limits.html
Pour plus de détails sur les autres attributs.
La façon iostream est un peu maladroit. Je préfère utiliser boost::lexical_cast
car il calcule la précision pour moi. Et il est rapide aussi.
#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;
Sortie:
Pi: 3,14159265358979
Voici comment afficher un double avec une précision complète:
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
Cette affiche:
100,0000000000005
max_digits10 est le nombre de chiffres qui sont nécessaires pour représenter de façon unique toutes les valeurs doubles distinctes. max_digits10 représente le nombre de chiffres avant et après la virgule.
Ne pas utiliser set_precision (max_digits10) avec std :: fixe.
Sur notation fixe, set_precision () définit le nombre de chiffres seulement après la virgule. Ceci est incorrect que max_digits10 représente le nombre de chiffres avant et après la virgule.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
affiche un résultat incorrect:
100,00000000000049738
Remarque: Les fichiers d'en-tête requis
#include <iomanip>
#include <limits>
En pleine précision, je suppose que dire assez de précision pour montrer la meilleure approximation à la valeur prévue, mais il convient de souligner que double
est stockée en utilisant la base 2 et la représentation base 2 ne peut pas représenter quelque chose d'aussi trivial que 1.1
exactement. La seule façon d'obtenir le plein complet précision de la double réelle (sans Complètent erreur) est d'imprimer les bits binaires (ou quartets hexagonaux). Une façon de faire qui est en train d'écrire le double
à un union
puis l'impression de la valeur de nombre entier de bits.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
Cela vous donnera la précision précis à 100% de la double ... et être tout à fait illisible parce que les humains ne peuvent pas lire à double format IEEE! Wikipedia a une bonne écriture sur la façon d'interpréter les bits binaires.
Dans les nouvelles C ++, vous pouvez faire
std::cout << std::hexfloat << 1.1;
Comment puis-je imprimer une valeur
double
avec toute la précision en utilisant Cout?
Utilisez hexfloat
ou
utiliser scientific
et définir la précision
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
Trop de réponses ne portent que sur une des 1) base 2) mise en page fixe / scientifique ou 3) la précision. Trop de réponses avec précision ne fournissent pas la valeur correcte nécessaire. D'où cette réponse à une vieille question.
- Qu'est-ce que la base?
A double
est certainement codé en utilisant la base 2. Une approche directe avec C ++ 11 est d'imprimer en utilisant std::hexfloat
.
Si une sortie non décimale est acceptable, nous fait.
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
- Dans le cas contraire:
fixed
ouscientific
A double
est un virgule flottante type pas point fixe .
Do pas utiliser std::fixed
que cela ne parvient pas à imprimer petite double
comme tout sauf 0.000...000
. Pour les grandes double
, il imprime beaucoup de chiffres, peut-être des centaines de informativité douteux.
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
Pour imprimer avec une précision complète, première std::scientific
d'utilisation qui « écrire des valeurs à virgule flottante en notation scientifique ». Notez la valeur par défaut de 6 chiffres après la virgule décimale, une quantité insuffisante, est traitée dans le point suivant.
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
- Combien de précision (combien de chiffres totaux)?
A double
codé binaire en utilisant la base 2 code pour la même précision entre diverses puissances de 2. Ceci est souvent 53 bits.
[1.0 ... 2.0), il existe 2 53 différent double
,
[2.0 ... 4.0) il y a 2 53 différent double
,
[4.0 ... 8.0) il y a 2 53 différent double
,
[8.0 ... 10.0) il y a 8.2 * 2 53 différent double
.
Pourtant, si code imprime en décimal avec N
chiffres significatifs, le nombre de combinaisons [1.0 ... 10.0) est 9/10 * 10 N .
Quelle que soit N
(précision) est choisie, il n'y aura pas un à un entre double
et texte décimal. Si un N
fixe est choisie, il sera parfois un peu plus ou moins que vraiment nécessaire pour certaines valeurs double
. On pourrait l'erreur trop peu (a)
ci-dessous) ou trop (b)
ci-dessous).
3 candidat N
:
a) Utiliser un N
donc lors de la conversion du texte double
texte, nous arrivons au même texte pour tous double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
b) Utiliser un N
donc lors de la conversion de double
texte-double
nous arrivons au même double
pour tous double
.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
Lorsque max_digits10
n'est pas disponible, notez qu'en raison de base 2 et la base 10 attributs, digits10 + 2 <= max_digits10 <= digits10 + 3
, nous pouvons utiliser digits10 + 3
pour assurer suffisamment de chiffres décimaux sont imprimés.
c) Utiliser un N
qui varie en fonction de la valeur.
Cela peut être utile lorsque le code veut afficher du texte minimal (N == 1
) ou exactement valeur d'un double
(N == 1000-ish
dans le cas de denorm_min
). Cependant, puisque c'est « travail » et non objectif de l'OP probable, il sera mis de côté.
Il est généralement b) qui est utilisé pour « imprimer une valeur de double
avec une précision complète ». Certaines applications peuvent préférer a) à l'erreur sur ne pas fournir trop d'informations.
Avec .scientific
, .precision()
définit le nombre de chiffres à imprimer après le point décimal, donc les chiffres de 1 + .precision()
sont imprimés. besoins du Code max_digits10
chiffres totaux si .precision()
est appelée avec un 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 moyens à virgule flottante, avec une précision de 12 chiffres.
Cout est un objet qui a un tas de méthodes que vous pouvez appeler pour changer la précision et la mise en forme de choses imprimées.
Il y a une opération SetPrecision (...), mais vous pouvez également définir d'autres choses comme la largeur d'impression, etc.
Recherchez dans Cout Référence de votre IDE.
La plupart portably ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;
Avec ostream :: précision (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
donnera
3.141592653589793, 2.718281828459045
Pourquoi vous avez à dire « +1 » Je n'ai aucune idée, mais le chiffre supplémentaire que vous en sortir est correct.