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

Я не вижу результата, который я ожидаю с математикой.Круглый.

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 ответов


ты на самом деле не в середине. MidpointRounding.ToEven указывает, что если бы у вас было число 99.965, т. е. 99.96500000[etc.], затем вы получите 99.96. С тех пор, как ты переходишь на математику.Раунд выше этой средней точки, он округляется.

Если вы хотите, чтобы ваш номер округлился до 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);
}

он округляется только до 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
>>>

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


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

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.


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

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


математика.Круглый округляет десятичное значение до указанного количества дробных разрядов.'при округлении 99.96500000, 2 раунда до 99.96 и 99.96500001 до 99.67. Он округляет полную стоимость.


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

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

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

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

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