J'ai donc eu la réponse à ma dernière question (je ne sais pas pourquoi je n'y ai pas pensé). J'imprimais une double
à l'aide de cout
qui a été arrondie lorsque je ne m'y attendais pas. Comment puis-je faire cout
imprimer une double
avec une précision maximale?
Vous pouvez définir la précision directement sur _std::cout
_ et utiliser le spécificateur de format std::fixed
.
_double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
_
Vous pouvez _#include <limits>
_ pour obtenir la précision maximale d'un float ou d'un double.
_#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
_
Utilisez std::setprecision
:
_std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
_
Voici ce que je voudrais utiliser:
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
Fondamentalement, le paquet de limites a des traits pour tous les types de construction.
L’un des traits des 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/limits/numeric_limits.html
Pour plus de détails sur les autres attributs.
La façon dont iostreams est assez maladroite. Je préfère utiliser boost::lexical_cast
car il calcule la bonne précision pour moi. Et c'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 absolue:
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
Cela affiche:
100.0000000000005
max_digits10 est le nombre de chiffres nécessaires pour représenter de manière unique toutes les valeurs doubles distinctes. max_digits10 représente le nombre de chiffres avant et après le point décimal.
N'utilisez pas set_precision (max_digits10) avec std :: fixed.
En notation fixe, set_precision () définit le nombre de chiffres niquement après le point décimal. Ceci est incorrect car max_digits10 représente le nombre de chiffres before et after le point décimal.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
Cela affiche un résultat incorrect:
100.00000000000049738
Remarque: Fichiers d'en-tête requis
#include <iomanip>
#include <limits>
Par pleine précision, je suppose que la précision moyenne est suffisante pour indiquer la meilleure approximation de la valeur recherchée, mais il convient de noter que double
est stocké à l'aide de la représentation en base 2 et que la base 2 ne peut pas représenter quelque chose d'aussi trivial que 1.1
exactement. Le seul moyen d'obtenir la précision complète-complète du double actuel (avec NO ROUND OFF ERROR) consiste à imprimer les bits binaires (ou hex nybbles). ) Une façon de faire est d'écrire la double
sur un union
, puis d'afficher la valeur entière des bits.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
Cela vous donnera la précision 100% précise du double ... et sera totalement illisible car les humains ne peuvent pas lire le double format IEEE! Wikipedia a une bonne écriture sur la façon d'interpréter les bits binaires.
En C++ plus récent, vous pouvez faire
std::cout << std::hexfloat << 1.1;
Comment imprimer une valeur
double
avec une précision complète en utilisant cout?
Utilisez hexfloat
ou
utilise scientific
et règle 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 traitent que de 1) la base 2) la mise en page fixe/scientifique ou 3) la précision. Trop de réponses avec la précision ne fournissent pas la valeur appropriée nécessaire. D'où cette réponse à une vieille question.
Une double
est certainement encodée en base 2. Une approche directe avec C++ 11 consiste à imprimer en utilisant std::hexfloat
.
Si une sortie non décimale est acceptable, nous avons terminé.
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
fixed
ou scientific
?Un double
est un type à virgule flottante et non à virgule fixe .
Ne pas utilisez std::fixed
car cela ne permet pas d’imprimer de petites double
comme autre chose que 0.000...000
. Pour les grands double
, il affiche plusieurs chiffres, peut-être des centaines d'informations discutables.
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 optimale, utilisez d’abord std::scientific
, qui "écrira des valeurs à virgule flottante en notation scientifique". Notez que la valeur par défaut de 6 chiffres après le point décimal, un montant insuffisant, est traitée au 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
Un double
codé à l'aide de la base binaire 2 code la même précision entre différentes puissances de 2. C'est souvent 53 bits.
[1.0 ... 2.0) il y a 253 différent double
,
[2.0 ... 4.0) il y a 253 différent double
,
[4.0 ... 8.0) il y a 253 différent double
,
[8.0 ... 10.0) il y a 2/8 * 253 différent double
.
Pourtant, si le code est imprimé en décimal avec N
chiffres significatifs, le nombre de combinaisons [1.0 ... 10.0) est de 9/10 * 10N.
Quel que soit le choix de N
(précision), il n’y aura pas de correspondance individuelle entre double
et le texte décimal. Si un N
fixe est choisi, il sera parfois légèrement plus ou moins que nécessaire pour certaines valeurs de double
. Nous pourrions nous tromper sur trop peu (a)
ci-dessous) ou trop souvent (b)
ci-dessous).
3 candidats N
:
a) Utilisez un N
donc lors de la conversion de texte -double
- texte, nous obtenons le même texte pour tous les double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
b) Utilisez un N
donc lors de la conversion de double
-text -double
, nous arrivons au même double
pour tout double
.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
Lorsque max_digits10
n'est pas disponible, notez qu'en raison des attributs de base 2 et 10, digits10 + 2 <= max_digits10 <= digits10 + 3
, nous pouvons utiliser digits10 + 3
pour nous assurer que suffisamment de chiffres décimaux sont imprimés.
c) Utilisez un N
variant avec la valeur.
Cela peut être utile lorsque le code veut afficher un texte minimal (N == 1
) ou la valeur exacte d'un double
(N == 1000-ish
dans le cas de denorm_min
). Pourtant, puisqu'il s'agit d'un "travail" et non d'un objectif probable pour OP, il sera mis de côté.
C'est généralement b) qui est utilisé pour "imprimer une valeur double
avec une précision absolue". Certaines applications peuvent préférer a) commettre une erreur en ne fournissant pas trop d'informations.
Avec .scientific
, .precision()
définit le nombre de chiffres à imprimer après le point décimal, de sorte que 1 + .precision()
chiffres soient imprimés. Le code nécessite max_digits10
nombre total de chiffres. .precision()
est appelé 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 signifie une 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 le formatage des documents imprimés.
Il existe une opération setprecision (...), mais vous pouvez également définir d'autres paramètres tels que la largeur d'impression, etc.
Cherchez le cout dans la référence de votre IDE.
Avec ostream :: precision (int)
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
va céder
3.141592653589793, 2.718281828459045
Pourquoi vous devez dire "+1" Je n'ai aucune idée, mais le chiffre supplémentaire que vous obtenez est correct.
Le plus portable ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;