La précision de la longue double sortie n'est pas correct. Qu'est-ce qui pourrait être erroné?
-
22-08-2019 - |
Question
J'ai un long double
constant que je suis en train soit comme const ou non-const. Il est plus (40 chiffres) que la précision d'un long double
sur mon poste de travail de test (19 chiffres).
Quand je l'imprime, il ne s'affiche à 19 chiffres de précision, mais à 16 ans.
Voici le code que je teste:
#include <iostream>
#include <iomanip>
#include <limits>
#include <cstdio>
int main ()
{
const long double constLog2 = 0.6931471805599453094172321214581765680755;
long double log2 = 0.6931471805599453094172321214581765680755;
std::cout << std::numeric_limits<long double>::digits10 + 1 << std::endl;
std::cout << "const via cout: " << std::setprecision(19) << constLog2 << std::endl;
std::cout << "non-const via cout: " << std::setprecision(19) << log2 << std::endl;
std::fprintf(stdout, "const via printf: %.19Lf\n", constLog2);
std::fprintf(stdout, "non-const via printf: %.19Lf\n", log2);
return 0;
}
Compiler:
$ g++ -Wall precisionTest.cpp
Sortie:
$ ./a.out
19
const via cout: 0.6931471805599452862
non-const via cout: 0.6931471805599452862
const via printf: 0.6931471805599452862
non-const via printf: 0.6931471805599452862
Je me attends 0.6931471805599453094
mais se 0.6931471805599452862
.
Y at-il une raison que les 19 chiffres de précision sont coupés à 16 chiffres?
Voici mon environnement:
$ gcc --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)
Je vois le même problème avec d'autres versions de gcc, par exemple:.
$ gcc --version
g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)
Je peux regarder dans NTL ou d'autres bibliothèques, mais je suis curieux de savoir ce qui cause cela. Merci pour votre perspicacité.
La solution
Je reçois cette sortie:
19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094
Mais je suis en utilisant de longues doubles littéraux au lieu de doubles littéraux:
const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;
Autres conseils
Il y a quelques questions subtiles concernant les plates-formes matérielles et des options de compilation qui pourraient intéresser:
- https://www.amazon.com/exec/obidos/ASIN/0954161793 / 20- théorie des réseaux
- 3.17.3 Intel 386 et AMD x86-64 options (gcc-4.0.1) (documentation developer.apple.com archivé)
- 17/03/12 Intel 386 et AMD x86-64 options (gcc-4.0.1) (documentation gcc.gnu.org)
Ces options `-m » sont définies pour la famille i386 et x86-64 des ordinateurs:
-m96bit long double
-m128bit long double
Ces commutateurs contrôlent la taille de type long double. L'application i386 interface binaire spécifie la taille soit 96 bits, de sorte que -m96bit-long double est la valeur par défaut en mode 32 bits. architectures modernes (Pentium et plus récent) préféreraient longtemps double pour être aligné à 8 ou 16 limite d'octet. Dans des tableaux ou des structures conforme à l'ABI, ce ne serait pas être possible. Ainsi, la spécification d'un -m128bit-longue à double alignera long double à une limite de 16 octets par imbiber le long double avec un zéro supplémentaire de 32 bits.
Dans le compilateur x86-64, -m128bit long double est le choix par défaut comme ABI précise que longue deux doit être aligné sur l'octet 16 frontière.
Notez que aucune de ces options permettre à toute précision supplémentaire sur la norme x87 de 80 bits pour une longue double.
Attention: si vous remplacez la valeur par défaut valeur pour votre cible ABI, la des structures et des tableaux contenant longtemps variables doubles changeront leur taille ainsi que l'appel de fonction Convention pour la fonction prise de temps deux seront modifiés. Par conséquent, ils ne sera pas binaire compatible avec des tableaux ou des structures dans le code compilé sans que l'interrupteur.