A falha da calculadora do Google pode flutuar vs.duplo ser uma razão possível?

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

  •  09-06-2019
  •  | 
  •  

Pergunta

Eu fiz isso apenas por diversão (então, não é exatamente uma pergunta, já posso ver o downmodding acontecendo), mas, no lugar do novo recurso do Google incapacidade pendência matemática corretamente (Confira!de acordo com o Google 500.000.000.000.002 - 500.000.000.000.001 = 0), pensei em tentar o seguinte em C para fazer um pouco de teoria.

int main()
{
   char* a = "399999999999999";
   char* b = "399999999999998";

   float da = atof(a);
   float db = atof(b);

   printf("%s - %s = %f\n", a, b, da-db);

   a = "500000000000002";
   b = "500000000000001";
   da = atof(a);
   db = atof(b);
   printf("%s - %s = %f\n", a, b, da-db);
}

Ao executar este programa, você obtém o seguinte

   399999999999999 - 399999999999998 = 0.000000
   500000000000002 - 500000000000001 = 0.000000

Parece que o Google está usando precisão flutuante simples de 32 bits (o erro aqui). Se você mudar float para double no código acima, você corrigirá o problema!Poderia ser isso?

/mp

Foi útil?

Solução

em C#, tente (double.maxvalue == (double.maxvalue - 100)) , você obterá a verdade ...

mas é isso que deveria ser:

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

pensando bem, você tem 64 bits representando um número maior que 2^64 (double.maxvalue), então é esperada imprecisão.

Outras dicas

Para saber mais sobre esse tipo de bobagem, consulte este belo artigo referente à calculadora do Windows.

Quando você muda o interior, ninguém percebe

As entranhas de Calc - o motor aritmético - foram completamente jogadas fora e reescritas do zero.A biblioteca padrão de ponto flutuante IEEE foi substituída por uma biblioteca aritmética de precisão arbitrária.Isso foi feito depois que as pessoas continuaram escrevendo artigos de Ha -ha sobre como Calc não poderia fazer a aritmética decimal corretamente, que, por exemplo, a computação 10.21 - 10.2 resultou em 0,0100000000000016.

Parece que o Google está usando precisão flutuante simples de 32 bits (o erro aqui). Se você mudar float para double no código acima, você corrigirá o problema!Poderia ser isso?

Não, você apenas adia o problema.as duplas ainda apresentam o mesmo problema, apenas com números maiores.

@ebel

pensando bem, você tem 64 bits representando um número maior que 2^64 (double.maxvalue), então é esperada imprecisão.

2 ^ 64 não é o valor máximo de um duplo.2 ^ 64 é o número de valores exclusivos que um double (ou qualquer outro tipo de 64 bits) pode conter. Double.MaxValue é igual a 1,79769313486232e308.

A imprecisão com números de ponto flutuante não vem da representação de valores maiores que Double.MaxValue (o que é impossível, excluindo Double.PositiveInfinity).Isso vem do fato de que o intervalo de valores desejado é simplesmente grande demais para caber no tipo de dados.Portanto, abrimos mão da precisão em troca de um alcance efetivo maior.Em essência, estamos eliminando dígitos significativos em troca de um intervalo de expoentes maior.

@DrPizza

Nem mesmo;as codificações IEEE usam múltiplas codificações para os mesmos valores.Especificamente, NaN é representado por um expoente de todos os bits-1 e, em seguida, qualquer valor diferente de zero para a mantissa.Como tal, existem 252 NaNs para duplas e 223 NaNs para simples.

Verdadeiro.Não considerei codificações duplicadas.Na verdade existem 252-1 NaNs para duplas e 223-1 NaNs para solteiros, no entanto.:p

2 ^ 64 não é o valor máximo de um duplo.2 ^ 64 é o número de valores exclusivos que um double (ou qualquer outro tipo de 64 bits) pode conter.Double.MaxValue é igual a 1,79769313486232e308.

Nem mesmo;as codificações IEEE usam múltiplas codificações para os mesmos valores.Especificamente, NaN é representado por um expoente de todos os bits-1 e então qualquer valor diferente de zero para a mantissa.Como tal, existem 252 NaNs para duplas, 223 NaNs para solteiros.

Verdadeiro.Não considerei codificações duplicadas.Na verdade, existem 252-1 NaNs para duplas e 223-1 NaNs para simples.:p

Ah, esqueci de subtrair os infinitos.

A versão aproximada desse problema que aprendi é que os floats de 32 bits fornecem 5 dígitos de precisão e os floats de 64 bits fornecem 15 dígitos de precisão.É claro que isso irá variar dependendo de como os carros alegóricos são codificados, mas é um bom ponto de partida.

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