Глиф Учебники

Как округлить число — Math.Round и банковское округление

Справочник · C# · 2 минуты чтения

C#
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
3

Math.Round по умолчанию округляет банковским способом: число ровно посередине (2.5, 3.5) округляется до ближайшего чётного. Поэтому 2,5 → 2, а 3,5 → 4. Остальные числа округляются как обычно: 2,6 → 3.

Школьное правило «пятёрка — вверх» (точнее, от нуля: 2,5 → 3, −2,5 → −3) включается вторым аргументом MidpointRounding.AwayFromZero.

Зачем банковское округление

Если всегда округлять половину вверх, при сложении тысяч округлённых чисел сумма систематически получается больше настоящей. Округление к чётному половину таких чисел отправляет вверх, половину вниз, и ошибки взаимно гасятся. Отсюда и название — так удобно считать деньги; это же правило принято по умолчанию в стандарте чисел с плавающей точкой IEEE 754.

До нужного числа знаков

Второй аргумент — сколько знаков оставить после запятой (вывод — с русскими региональными настройками, через запятую):

C#
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.

Вниз, вверх, отбросить

C#
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);.

Подводные камни