Получение другого результата в Math.Round - PullRequest
0 голосов
/ 22 октября 2009
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 различным результатам

Ответы [ 5 ]

4 голосов
/ 22 октября 2009

Это старый регистр чисел с плавающей запятой, которые не могут представлять десятичные числа точно .

Вы, похоже, имеете дело с деньгами, и тогда вам действительно стоит подумать об использовании десятичного .

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));
1 голос
/ 22 октября 2009

Простой ответ заключается в том, что это связано с ошибкой округления в уравнениях, использующих числа с плавающей запятой. Это потому, что, как правило, нет точного двоичного представления числа с плавающей запятой, поэтому все, что у вас есть, это приближения.

Я заметил, что у вас есть:

(percentageToRefund * 0.01)

в первом уравнении и:

(percentageToRefund * 0.01) * 100

во втором.

Это последнее выражение приведет к ошибке округления, так как вы сначала делите на 100, а затем умножаете на 100. Входные данные не будут равны выходным, разница зависит от архитектуры машины, ОС, языка и компилятора.

Если вы имеете дело с деньгами, вы должны использовать тип decimal (при условии C #)

0 голосов
/ 22 октября 2009

Это связано с конечной точностью чисел с плавающей запятой.

0 голосов
/ 22 октября 2009

Короче говоря. Это связано с ошибками точности при представлении значений с плавающей точкой в ​​виде двоичных данных. По сути, это означает, что вы не можете представить каждое возможное число с плавающей запятой 32/64 битами, поэтому в действительности 2.1 - это 2.1000000000000001 и т. Д. Это одна из причин, почему вы никогда не должны делать что-то вроде 2.145 == «другое значение, которое должно быть 2.145».

Предлагаю прочитать статью в Википедии для получения более подробной информации: Wiki Link

0 голосов
/ 22 октября 2009

Потому что число с плавающей точкой не является точным. Я рекомендую прочитать http://en.wikipedia.org/wiki/Floating_point. Вы поймете, почему результат отличается.

...