Pergunta

Estou fazendo uma aritmética de ponto flutuante e tendo problemas de precisão. O valor resultante é diferente em duas máquinas para a mesma entrada. Eu li o post @ Por que não consigo multiplicar um flutuador? E também leia outro material na web e entendeu que isso tem a ver com a representação binária do ponto flutuante e no Machine Epsilon. No entanto, eu queria verificar se existe uma maneira de resolver esse problema / algum contorno para a aritmética de ponto flutuante em C ++ ?? Estou convertendo um flutuador em curta duração não assinada para armazenamento e estou convertendo para trás quando necessário. No entanto, quando eu o converto de volta ao curto não assinado, a precisão (para 6 pontos decimais) permanece correta em uma máquina, mas falha na outra.

//convert FLOAT to short

unsigned short sConst = 0xFFFF;

unsigned short shortValue = (unsigned short)(floatValue * sConst);

//Convert SHORT to FLOAT

float floatValue = ((float)shortValue / sConst);
Foi útil?

Solução

UMA short Deve ter pelo menos 16 bits e, em muitas implementações, é exatamente o que é. Um unsigned 16 bits short manterá valores de 0 a 65535. Isso significa que um curto não realizará cinco dígitos completos de precisão, e certamente não seis. Se você deseja seis dígitos, precisa de 20 bits.

Portanto, qualquer perda de precisão provavelmente se deve ao fato de você estar tentando embalar seis dígitos de precisão em algo inferior a cinco dígitos. Não há solução para isso, além de usar um tipo integral que provavelmente leva tanto armazenamento quanto um float.

Não sei por que parece funcionar em um determinado sistema. Você estava usando os mesmos números em ambos? Um usou um sistema de ponto flutuante mais antigo e que coincidentemente deu os resultados que você esperava nas amostras que você tentou? Estava possivelmente usando um maior short do que o outro?

Outras dicas

Se você deseja usar os tipos de pontos flutuantes nativos, o melhor que você pode fazer é afirmar que os valores que a saída pelo seu programa não diferem muito de um conjunto de valores de referência.

A definição precisa de "demais" depende inteiramente do seu aplicativo. Por exemplo, se você calcular a + b Em diferentes plataformas, você deve encontrar os dois resultados dentro da precisão da máquina. Por outro lado, se você estiver fazendo algo mais complicado, como a inversão da matriz, os resultados provavelmente diferirão mais do que a precisão da máquina. Determinar com precisão o quão perto você pode esperar que os resultados estejam entre si é um processo muito sutil e complicado. A menos que você saiba exatamente o que está fazendo, provavelmente é mais seguro (e muito mais) determinar a quantidade de precisão que você precisa a jusante em seu aplicativo e verifique se o resultado é suficientemente preciso.

Para ter uma idéia sobre como calcular o erro relativo entre dois valores de ponto flutuante de forma robusta, consulte esta resposta e o guia de ponto flutuante vinculado nela:

Funções de comparação de pontos flutuantes para C#

Em vez de usar 0xffff, use metade dele, ou seja, 32768 para conversão. 32768 (OX8000) possui uma representação binária de 100000000000000000, enquanto o Oxffff tem uma representação binária de 111111111111111111. A representação binária do OX8000 implica claramente, as operações de multiplicação e divisão durante a conversão (para curta (ou) durante a conversão para voltar a flutuar) não mudarão os valores de precisão depois de zero. Para uma conversão lateral, no entanto, o Oxffff é preferível, pois leva a um resultado mais preciso.

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