Что не так с Math.Round() в VB.Net?
У меня такой странный случай в функции Math.Round в VB.Net
Math.Round((32.625), 2)
Результат: 32,62
Math.Round((32.635), 2)
Результат: 32,64
Мне нужно 32.63, но в этих случаях функция работает в другой логике.
Я могу получить десятичную часть и сделать то, что я хочу, что-то сделать с ней. Но не слишком ли это странно, кто-то округляется до более высокого, кто-то округляется до более низкого?
Итак, как я могу получить 32,63 из 32,625 без возни с десятичной частью? (как естественная логика математики)
5 ответов
Math.Round
по умолчанию использует банковское округление. Вы можете изменить это, указав другой MidPointRounding
вариант. Из MSDN:
Скругление от нуля
Значения средней точки округляются до следующего числа от нуля. Например, 3,75 раунда до 3,8, 3,85 раунда до 3,9, -3,75 раунда до -3,8 и -3,85 раунда до -3,9. Эта форма округления представлена элементом перечисления MidpointRounding.AwayFromZero. Скругление от нуля является наиболее широко известной формой округления.
Округление до ближайшего или банковское округление
Средние значения округляются до ближайшего четного числа. Например, 3,75 и 3,85 округляют до 3,8, а оба -3,75 и -3,85 округляют до -3,8. Эта форма округления представлена элементом перечисления MidpointRounding.ToEven.
Округление до ближайшего является стандартной формой округления, используемой в финансовых и статистических операциях. Он соответствует стандарту IEEE 754, раздел 4. При использовании в нескольких операциях округления он уменьшает ошибку округления, вызванную последовательным округлением значений средней точки в одном направлении. В некоторых случаях эта ошибка округления может быть значительной.
Итак, что вы хотите, это:
Math.Round(32.625, 2, MidpointRounding.AwayFromZero)
Math.Round(32.635, 2, MidpointRounding.AwayFromZero)
Как уже упоминали другие, если точность важна, вы должны использовать Decimal
переменные, а не типы с плавающей запятой. Например:
Math.Round(32.625D, 2, MidpointRounding.AwayFromZero)
Math.Round(32.635D, 2, MidpointRounding.AwayFromZero)
Попробуйте это (из памяти):
Math.Round((32.635), 2, MidPointRounding.AwayFromZero)
Попробуй это.
Dim d As Decimal = 3.625
Dim r As Decimal = Math.Ceiling(d * 100D) / 100D
MsgBox(r)
Это должно делать то, что вы хотите.
Это быстрая функция, которую вы можете добавить, чтобы упростить свою жизнь и сделать так, чтобы вам не приходилось так много печатать все время.
Private Function roundd(dec As Decimal)
Dim d As Decimal = dec
Dim r As Decimal = Math.Ceiling(d * 100D) / 100D
Return r
End Function
Добавьте это в ваше приложение, затем используйте функцию
roundd(3.624)
или что вам нужно.
показать результат - пример
msgbox(roundd(3.625))
Это отобразит окно сообщения с 3,63
Textbox1.text = roundd(3.625)
это установит textbox1.text - 3.63 и т. д. и т. д. Поэтому, если вам нужно округлить более одного числа, это не будет таким утомительным занятием, и вы сможете сэкономить много печатать.
Надеюсь это поможет.
Вы не можете использовать числа с плавающей точкой, это то, что числа, подобные 32.625, обрабатываются как в VB.Net. (Существует также проблема округления Банкира, как упомянуто @StevenDoggart - вам, вероятно, придется столкнуться с обоими проблемами.)
Проблема заключается в том, что сохраненное число не совсем то, что введено, потому что эти числа не находятся в фиксированном двоичном представлении, например, 32.625 хранится как 32.62499997 и 32.635 как 32.63500001.
Единственный способ быть точным - хранить числа как десятичные
DIM num as Decimal
num = ToDecimal("32.625")