문제
ticketPriceInPence = 7360
percentageToRefund = 100
(int)(Math.Round((ticketPriceInPence * 0.01) * (percentageToRefund * 0.01), 2, MidpointRounding.AwayFromZero) * 100)
결과 : 73.59
(int)(Math.Round((ticketPriceInPence * 0.01) * (percentageToRefund * 0.01) * 100, 2, MidpointRounding.AwayFromZero))
결과 : 73.60
왜 다른 2 가지 결과를 초래하는지 아는 것
해결책
그건 오래된 경우 부동 소수점 번호는 할 수 없습니다 정확히 소수성을 나타냅니다.
당신은 여기서 돈을 다루고있는 것 같고 실제로 사용을 고려해야합니다. 소수.
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));
다른 팁
간단한 대답은 부동 소수점 번호를 사용하는 방정식의 반올림 오류 때문이라는 것입니다. 이것은 일반적으로 부동 소수점 번호의 정확한 이진 표현이 없기 때문에 근사치 만 있으면됩니다.
나는 당신이 가지고있는 것을 알았습니다.
(percentageToRefund * 0.01)
첫 번째 방정식에서 :
(percentageToRefund * 0.01) * 100
두 번째.
후자의 표현식은 처음 100으로 나누고 다시 100을 곱하면 반올림 오류를 초래할 것입니다. 입력은 기계 아키텍처, OS, 언어 및 컴파일러에 따라 출력, 차이와 같지 않습니다.
돈을 다루고 있다면 사용해야합니다 decimal
유형 (C#가정)
플로트는 정확한 숫자가 아니기 때문입니다. 나는 읽는 것이 좋습니다 http://en.wikipedia.org/wiki/floating_point. 결과가 다른 이유를 알 수 있습니다.
짧은 이야기. 플로트 값을 이진 데이터로 나타낼 때 정밀한 오류 때문입니다. 즉, 기본적으로 32/64 비트로 가능한 모든 플로트를 대표 할 수는 없으므로 실제로 2.1은 2.1000000000000001 등입니다. 이것이 2.145 == "2.145 여야하는 기타 값"과 같은 일을하지 말아야 할 이유 중 하나입니다.
자세한 정보는 Wikipedia의 기사를 읽는 것이 좋습니다. 위키 링크
이것은 부동 소수점 번호의 유한 정밀성 때문입니다.