.Net Rounding Issue - PullRequest
       2

.Net Rounding Issue

12 голосов
/ 19 октября 2010

У меня проблема округления внутри .Net.

Я округляю трехзначное число до двух цифр, и это вызывает некоторые проблемы с одним числом.

Если я пытаюсьокруглить 34,425 до двух знаков после запятой, следует округлить до 34,43.Я использую опцию roundawayfromzero, и она сработала для каждого числа в программе, кроме этого.

Код Math.Round(34.425, 2, MidpointRounding.AwayFromZero) должен равняться 34,43, однако он равен 34,42.

ЕслиЯ пробую это с любым другим номером, он работает нормально.

Math.Round(34.435, 2, MidpointRounding.AwayFromZero) = 34.44

Math.Round(34.225, 2, MidpointRounding.AwayFromZero) = 34.23

Math.Round(34.465, 2, MidpointRounding.AwayFromZero) = 34.47

Я просто хотел проверить, сталкивался ли кто-нибудь с этой проблемой раньше?

На данный момент я исправил эту проблемупутем преобразования числа в десятичное число.Я изменил код на этот, и теперь он работает нормально:

Math.Round(CDec(34.425), 2, MidpointRounding.AwayFromZero) = 34.43

Я просто ищу причину, по которой мой старый код не работает.

Спасибо!

Обновлен код до правильного AwayFromZero

Ответы [ 5 ]

20 голосов
/ 19 октября 2010

Плавающая точка никогда не бывает точной, 34,425 может иметь внутреннюю репрезентацию 34,4249999999999 .. которая будет округлена до 34,42.

Если вам нужно точное представление чисел, используйте тип decimal.

2 голосов
/ 19 октября 2010

Немного смущен тем, используете ли вы на самом деле MidpointRounding.ToEven или MidpointRounding.AwayFromZero.Если вы используете ToEven в качестве первого фрагмента, это ожидаемое поведение.

1 голос
/ 19 октября 2010

Код Math.Round (34.425, 2, MidpointRounding.ToEven) должен быть равен 34,43, но равен 34,42.

Почему? ToEven должен сделать это 34,42, так как 42 четный. Поведение правильное.

1 голос
/ 19 октября 2010

Ваши предположения и результаты неверны:

Math.Round(34.225, 2, MidpointRounding.ToEven) == 34.22
Math.Round(34.465, 2, MidpointRounding.ToEven) == 34.46

и

Math.Round(34.425, 2, MidpointRounding.ToEven) == 34.42

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

0 голосов
/ 19 октября 2010

Я не использую vb.net, поэтому мои рассуждения могут быть неверными, но исходя из имен ваших параметров MidpointRounding.ToEven, я ожидаю, что 34,425 будет округлено до 34,42;но я бы также ожидал, что 34,225 будет округлено до 34,22 и 34,465 до 34,46.Округление чисел, оканчивающихся на 5, как в ваших примерах, является условным.Самым обычным соглашением является округление до четного числа, которое, как я понимаю, должен принимать ваш параметр .ToEven.

Кроме того, я подозреваю, что вы столкнулись с проблемой двоичного / десятичного округления.Проверка двоичного представления 34.425 выглядит как 10010.011011 ....... Если принять во внимание память компьютера и представление десятичного числа (байт, слово, двойное слово, четверное слово и отрицательное / положительное дополнение), это может привести кесли вы не округлили число, которое, как вы думали, было.

Чтобы получить требуемые результаты, вам, вероятно, следует добавить 0,00001 к любой цифре, заканчивающейся на 5, перед округлением.

...