Pergunta

ticketPriceInPence = 7360
percentageToRefund = 100

(int)(Math.Round((ticketPriceInPence * 0.01) * (percentageToRefund * 0.01), 2, MidpointRounding.AwayFromZero) * 100)

Isso resulta em: 73,59

(int)(Math.Round((ticketPriceInPence * 0.01) * (percentageToRefund * 0.01) * 100, 2, MidpointRounding.AwayFromZero))

Isso resulta em: 73.60

Qualquer idéia porque ele resulta em diferentes 2 resultados diferentes

Foi útil?

Solução

É a velho caso de números de ponto flutuante não ser capaz representam decimais exatamente .

Você parece estar lidando com dinheiro aqui e então você realmente deve considerar o uso de decimal .

decimal ticketPriceInPence = 7360;
decimal percentageToRefund = 100;
var result1 = (int)(Math.Round((ticketPriceInPence * 0.01m) * (percentageToRefund * 0.01m), 2, MidpointRounding.AwayFromZero) * 100);
var result2 = (int)(Math.Round((ticketPriceInPence * 0.01m) * (percentageToRefund * 0.01m) * 100, 2, MidpointRounding.AwayFromZero));

Outras dicas

A resposta simples é que é devido ao erro de arredondamento em equações usando números de ponto flutuante. Isso ocorre porque, em geral, não há representação sem exata binária de um número de ponto flutuante por isso tudo que você tem é aproximações.

Eu noto que você tem:

(percentageToRefund * 0.01)

na primeira equação, e:

(percentageToRefund * 0.01) * 100

no segundo.

Esta última expressão resultará em erro de arredondamento como você é primeiro dividir por 100, em seguida, multiplicando por 100 novamente. A entrada não será igual a saída, a diferença dependendo da arquitetura da máquina, sistema operacional, linguagem e compilador.

Se você está lidando com o dinheiro que você deve usar o tipo decimal (assumindo C #)

Porque uma bóia não é um número exato. Eu recomendo a leitura http://en.wikipedia.org/wiki/Floating_point . Você vai ver porque o resultado é diferente.

Para encurtar a história. É por causa de Erros de precisão quando representam valores float como dados binários. Isso basicamente significa que você não pode representar todos os possíveis flutuador com 32/64 bits, então 2.1 na realidade é 2,1000000000000001 etc. Essa é uma razão pela qual você nunca deve fazer algo como 2,145 == "outro valor que deverá ser 2,145".

Eu sugiro a leitura do artigo na Wikipedia para obter informações mais detalhadas: Wiki Fazer a ligação

Isto é devido à precisão finita de números de ponto flutuante.

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