Как округлить число — Math.Round и банковское округление
Console.WriteLine(Math.Round(2.5));
Console.WriteLine(Math.Round(3.5));
Console.WriteLine(Math.Round(-2.5));
Console.WriteLine(Math.Round(2.5, MidpointRounding.AwayFromZero));
Console.WriteLine(Math.Round(2.6));2
4
-2
3
3Math.Round по умолчанию округляет банковским способом: число ровно посередине (2.5, 3.5) округляется до ближайшего чётного. Поэтому 2,5 → 2, а 3,5 → 4. Остальные числа округляются как обычно: 2,6 → 3.
Школьное правило «пятёрка — вверх» (точнее, от нуля: 2,5 → 3, −2,5 → −3) включается вторым аргументом MidpointRounding.AwayFromZero.
Зачем банковское округление
Если всегда округлять половину вверх, при сложении тысяч округлённых чисел сумма систематически получается больше настоящей. Округление к чётному половину таких чисел отправляет вверх, половину вниз, и ошибки взаимно гасятся. Отсюда и название — так удобно считать деньги; это же правило принято по умолчанию в стандарте чисел с плавающей точкой IEEE 754.
До нужного числа знаков
Второй аргумент — сколько знаков оставить после запятой (вывод — с русскими региональными настройками, через запятую):
Console.WriteLine(Math.Round(3.14159, 2));
Console.WriteLine(Math.Round(1.125, 2));
Console.WriteLine(Math.Round(1.125, 2, MidpointRounding.AwayFromZero));
Console.WriteLine(Math.Round(2.345m, 2));
Console.WriteLine(Math.Round(2.345m, 2, MidpointRounding.AwayFromZero));3,14
1,12
1,13
2,34
2,35Числа 2.345m с буквой m — decimal. У double большинство десятичных дробей хранится приближённо, поэтому «середина» вроде 2,345 на деле может оказаться чуть меньше или чуть больше и округлиться неожиданно. Для денег берите decimal: там 2,345 — ровно 2,345.
Вниз, вверх, отбросить
Console.WriteLine(Math.Floor(2.7));
Console.WriteLine(Math.Ceiling(2.1));
Console.WriteLine(Math.Floor(-2.7));
Console.WriteLine(Math.Truncate(-2.7));
Console.WriteLine((int)2.99);2
3
-3
-2
2| Метод | Что делает |
|---|---|
Math.Floor(x) | вниз, к меньшему: −2,7 → −3 |
Math.Ceiling(x) | вверх, к большему: 2,1 → 3 |
Math.Truncate(x) | отбросить дробную часть: −2,7 → −2 |
(int)x | то же, что Truncate, и сразу в int |
Math.Round, Floor и Ceiling возвращают double (или decimal), а не int. Чтобы получить целое, приведите результат: int n = (int)Math.Round(x);.
Подводные камни
Convert.ToInt32(2.5)тоже округляет банковским способом и даёт 2, аConvert.ToInt32(3.5)— 4.- Округление и вывод — разные вещи.
Math.Roundменяет само число, а формат{x:F2}только печатает его с двумя знаками — справка Как вывести число с двумя знаками после запятой. Math.Round(-0.4)даёт «отрицательный ноль», иConsole.WriteLineпечатает его как-0. Если это мешает, прибавьте к результату0.0или выводите через формат.- В других языках правила свои: в Python
roundтоже банковский, а в JavaScriptMath.round(2.5)— 3. Переносите расчёты между языками осторожно.