Pergunta

(int)(33.46639 * 1000000) retorna 33466389

Por que isso acontece?

Foi útil?

Solução

A matemática de ponto flutuante não é perfeito. O que todo programador deve saber sobre isso.

A aritmética de ponto flutuante é considerado um sujeito esotérico por muitas pessoas. Isso é surpreendente porque o ponto flutuante é onipresente nos sistemas de computador. Quase todo idioma tem um tipo de dados de ponto flutuante; computadores de PCs a supercomputadores têm aceleradores de ponto flutuante; A maioria dos compiladores será chamada a compilar algoritmos de ponto flutuante de tempos em tempos; e praticamente todo sistema operacional deve responder a exceções de ponto flutuante, como o transbordamento. Este artigo apresenta um tutorial sobre os aspectos do ponto flutuante que têm um impacto direto nos designers de sistemas de computador. Começa com o fundo da representação de ponto flutuante e do erro de arredondamento, continua com uma discussão sobre o padrão de ponto flutuante IEEE e termina com vários exemplos de como os construtores de computadores podem suportar melhor o ponto flutuante.

...

Espreitar infinitamente muitos números reais em um número finito de bits requer uma representação aproximada. Embora existam infinitamente muitos números inteiros, na maioria dos programas, o resultado de cálculos inteiros pode ser armazenado em 32 bits. Por outro lado, dado qualquer número fixo de bits, a maioria dos cálculos com números reais produzirá quantidades que não podem ser exatamente representadas usando tantos bits. Portanto, o resultado de um cálculo de ponto flutuante deve ser frequentemente arredondado para se encaixar em sua representação finita. Esse erro de arredondamento é o recurso característico do computação de ponto flutuante.

Outras dicas

A precisão dupla não é exata, portanto, internamente 33.46639 é realmente armazenado como 33.466389

EDIT: Como Richard disse, são dados de ponto flutuante (armazenados em binário em um conjunto finito de bits) para que não seja exatamente isso) ....

Era véspera de ano novo no final de 1994. Andy Grove, CEO da Intel, estava saindo de um ótimo ano, com o processador Pentium saindo e sendo um grande sucesso. Então, ele entrou em um bar e pediu um tiro duplo da gravadora Johnnie Walker Green.

O barman serviu e disse: "Isso custará US $ 20, senhor".

Grove colocou uma nota de vinte dólares no balcão, olhou para ela por um momento e disse: "Mantenha a mudança".

http://en.wikipedia.org/wiki/pentium_fdiv_bug

O motivo é que 33.46639 serão representados como algo um pouco menor que esse número.

A multiplicação por 1000000 fornecerá 33466389.99999999.

Casting de tipo usando (int) apenas retornará a parte inteira (33466389).

Se você deseja o número "correto", tente redondo () antes do tipo de fundição.

Se você está perguntando por que não se torna 33466390, é porque doubleS não têm precisão infinita e o número não pode ser expresso exatamente em binário.

Se você substituir o double com um decimal ((int)(33.46639m * 1000000)), é igual a 33466390, Porque decimalS são calculados na base 10.

Porque 33.46639 não pode ser expresso exatamente em um número finito de dígitos binários. O resultado real de 33.46639 * 1000000 é 33466389.9999999962747097015380859375. O elenco o trunca para 33466389.

A razão pela qual você obteve um resultado diferente é o fato de você ter usado um 'elenco'

(int)(33.46639 * 1000000) returns 33466389
^^^^^

Para lançar o resultado para um tipo de 'int' ... que arredondou para cima ou para baixo do tipo integral quando multiplicado e depois convertido em 'int' .... não confie no ponto flutuante para ser preciso o suficiente ... .Skeet postou uma excelente introdução em seu site aqui e aqui...

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