Ответ 1
Плавающая точка никогда не бывает точной, 34.425 может иметь внутреннюю репрезентацию 34.4249999999999.. которая будет округлена до 34.42.
Если вам нужно точное представление чисел, используйте тип decimal
.
У меня проблема округления внутри .Net.
Я округляю 3-значное число до двух цифр, и это вызывает некоторые проблемы с одним номером.
Если я попытаюсь округлить 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
Плавающая точка никогда не бывает точной, 34.425 может иметь внутреннюю репрезентацию 34.4249999999999.. которая будет округлена до 34.42.
Если вам нужно точное представление чисел, используйте тип decimal
.
Немного смущен, действительно ли вы используете MidpointRounding.ToEven
или MidpointRounding.AwayFromZero
. Если вы используете ToEven
, как показывает первый фрагмент, это ожидаемое поведение.
Ваши предположения и результаты неверны:
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
То, как это работает, и то, что я получаю на своей коробке. Округление означает даже это, округляя вверх или вниз, чтобы перейти к следующему четному числу в десятичной точке.
Код Math.Round(34.425, 2, MidpointRounding.ToEven) должен равняться 34.43, однако он равен 34.42.
Почему? ToEven должен сделать это 34.42, так как 42 четный. Поведение правильное.
Я не использую 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, перед округлением.