2010-10-19 2 views
12

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

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

Если я попытаюсь округлить 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

ответ

20

с плавающей точкой не точно, 34,425 может иметь внутреннее ПРЕДСТАВЛЕНИЕ 34.4249999999999 .. который будет округлены до 34.42.

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

+1

+1 для десятичного предложения –

+0

Благодарим за отзыв. На мой большой вопрос, почему это работает для всех других ценностей? – Jeff

+0

Я бы тоже согласился с вами, если бы это была переменная. Тем не менее, я помещал это значение в список наблюдения как 34.425. Поэтому его не следует представлять как 34.43499999 ... Это правильно в моем предположении? – Jeff

2

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

+0

Я отредактировал вопрос, извините за путаницу. – Jeff

1

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

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

Извините, я скопировал неправильный код. Все они должны быть AwayFromZero. – Jeff

+0

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

1

Код Math.Round (34.425, 2, MidpointRounding.ToEven) должен равняться 34.43, однако он равен 34.42.

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

0

Я не использую 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 до округления.