Что не так с 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")
Другие вопросы по тегам