Pergunta

Eu tenho uma constante long double que estou definindo quer como const ou não-const. É mais longos (40 dígitos) do que a precisão de um long double no meu trabalho de teste (19 dígitos).

Quando eu imprimi-lo, já não é exibido em 19 dígitos de precisão, mas aos 16 anos.

Aqui está o código que estou testando:

#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;
}

Compilar:

$ g++ -Wall precisionTest.cpp

Output:

$ ./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

Eu esperaria 0.6931471805599453094 mas sim obter 0.6931471805599452862.

Existe uma razão que os 19 dígitos de precisão são cortadas para 16 dígitos?

Aqui está o meu ambiente:

$ gcc --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)

Eu estou vendo o mesmo problema com outras versões do gcc, p.ex.:.

$ gcc --version
g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)

Eu posso olhar para NTL ou outras bibliotecas, mas estou curioso o que está causando isso. Obrigado pela sua compreensão.

Foi útil?

Solução

Eu recebo esta saída:

19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094

Mas eu estou usando literais longa casal em vez de literais duplas:

const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;    

Outras dicas

Existem alguns problemas sutis relacionados com plataformas de hardware e opções de compilação que possam ser de interesse:

Estas `opções -m' são definidos para o i386 e x86-64 família de computadores:

-m96bit-long-double

-m128bit-long-double

Estes interruptores controlar o tamanho do tipo double long. A interface binária i386 aplicação especifica o tamanho para ser de 96 bits, então -m96bit-long-dupla é o padrão no modo de 32 bits. arquiteturas modernas (Pentium e mais recentes) prefere longo duplo para ser alinhado a um 8 ou 16 byte fronteira. Em matrizes ou de estruturas em conformidade com a ABI, isso não faria seja possível. Então, especificando um -m128bit-longo-dupla irá alinhar longo duplo para um limite de 16 bytes pela preenchimento do long double com um de 32 bit zero.

No compilador x86-64, -m128bit-long-dupla é a opção padrão como seus especifica ABI tanto tempo duplo é para ser alinhado no byte 16 fronteira.

Observe que nenhuma dessas opções permitir que qualquer precisão extra sobre o x87 padrão de 80 bits para um longo Duplo.

Aviso: se você substituir o padrão valor para o seu alvo ABI, o estruturas e matrizes contendo longo variáveis ??duplas vai mudar a sua função de chamada, bem como o tamanho convenção para a tomada de função longo dupla será modificado. Daí eles não vai ser binário compatível com matrizes ou de estruturas em código compilado sem que o interruptor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top