Округление даже в C # - PullRequest
       7

Округление даже в C #

9 голосов
/ 14 сентября 2009

Я не вижу ожидаемого результата с Math.Round.

return Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97

Как я понимаю, MidpointRounding.ToEven, 5 в тысячной позиции должно привести к тому, что результат будет 99,96. Разве это не так?

Я даже попробовал это, но он также вернул 99,97:

return Math.Round(99.96535789 * 100, MidpointRounding.ToEven)/100;

Чего мне не хватает

Спасибо!

Ответы [ 7 ]

25 голосов
/ 14 сентября 2009

Вы на самом деле не в средней точке. MidpointRounding.ToEven означает, что если бы у вас было число 99,965 , т.е. 99,96500000 [и т. Д.], , тогда вы получите 99,96. Поскольку число, которое вы передаете в Math.Round выше этой средней точки, оно округляется в большую сторону.

Если вы хотите, чтобы ваш номер округлился до 99,96, сделайте следующее:

// this will round 99.965 down to 99.96
return Math.Round(Math.Truncate(99.96535789*1000)/1000, 2, MidpointRounding.ToEven);

И, эй, вот небольшая удобная функция для выполнения вышеперечисленного в общих случаях:

// This is meant to be cute;
// I take no responsibility for floating-point errors.
double TruncateThenRound(double value, int digits, MidpointRounding mode) {
    double multiplier = Math.Pow(10.0, digits + 1);
    double truncated = Math.Truncate(value * multiplier) / multiplier;
    return Math.Round(truncated, digits, mode);
}
9 голосов
/ 14 сентября 2009

Он округляется до 99,96, только если вы находитесь в средней точке, т.е. 99,965:

C:\temp>ipy
IronPython 2.6 Beta 2 (2.6.0.20) on .NET 2.0.50727.4927
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> from System import Math, MidpointRounding
>>> Math.Round(99.9651, 2, MidpointRounding.ToEven)
99.97
>>> Math.Round(99.965, 2, MidpointRounding.ToEven)
99.96
>>> Math.Round(99.9649, 2, MidpointRounding.ToEven)
99.96
>>> Math.Round(99.975, 2, MidpointRounding.ToEven)
99.98
>>>
4 голосов
/ 14 сентября 2009

Значение MidpointRounding вступает в игру только тогда, когда вы пытаетесь округлить значение, у которого наименее значимая цифра ровно 5. Другими словами, значение должно быть 99.965, чтобы получить Ваш желаемый результат. Поскольку здесь это не так, вы просто соблюдаете стандартный механизм округления. См. MSDN страницу для получения дополнительной информации.

3 голосов
/ 14 сентября 2009

Вот результаты, которые проливают свет на эту тему:

Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97
Math.Round(99.965, 2, MidpointRounding.ToEven);      // returning 99.96
Math.Round(99.96500000, 2, MidpointRounding.ToEven); // returning 99.96

Средняя точка равна 5 ... не 535789, а не 499999.

0 голосов
/ 20 ноября 2010

Если бы это был я, я бы не использовал Math.Round(), потому что это не то, чего вы пытаетесь достичь.

Вот что я бы сделал:

double num = 99.96535789;
double percentage = Math.Floor(100 * num) / 100;  

Который намного легче читать и является скорее математическим подходом.
Я умножил число на 100, теперь у меня есть 9996.535789.
Затем выведите его, который отличается от округления, чтобы вернуть наименьшее целое число, ближайшее к числу, чтобы получить 9996.
Затем я делю на 100, чтобы получить необходимое 99.96.

приписка
Этаж противоположен потолку , который возвращает наибольшее целое число, ближайшее к числу.
Итак, потолок 9996.535789 составляет 9997.
Они отличаются от округлением до десятичных точек, что фактически возвращает самое близкое целое число к числу, независимо от того, меньше оно или больше - в зависимости от того, что ближе всего; вот почему вы получали 99.97, когда использовали округление .

0 голосов
/ 14 сентября 2009

Math.Round 'Округляет десятичное значение до указанного числа дробных цифр.' при округлении от 99,96500000,2 до 99,96 и от 99,96500001 до 99,67. Округляет полное значение.

0 голосов
/ 14 сентября 2009

Округление средней точки просматривается, только если значение находится между вашими двумя делами.

В вашем случае это не "5", это "535 ...", так что оно больше средней точки и выполняется до 0,96. Чтобы получить ожидаемое поведение, вам нужно усечь до третьего знака после запятой, а затем округлить, используя MidpointRounding.ToEven.

...