La précision de la longue double sortie n'est pas correct. Qu'est-ce qui pourrait être erroné?

StackOverflow https://stackoverflow.com/questions/684112

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é.

Était-ce utile?

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:

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top