Целочисленное деление и округление в C#
При делении одного целочисленного значения на другое с помощью оператора деления
Причину этого поведения я описывал в предыдущей заметке - целочисленные аргументы приводят к целочисленному результату.
При попытке поделить на значение, равное
При попытке поделить на литерал
💬 Тем удивительнее оказывается тот факт, что в случае деления числа с плавающей точкой на ноль (
#basics
При делении одного целочисленного значения на другое с помощью оператора деления
/
результат всегда округляется до нуля. Другими словами- обрезается:int n1 = 7 / 2; // 3
long n2 = -7 / 2; // -3
short n3 = -11 / -3; // 3
Причину этого поведения я описывал в предыдущей заметке - целочисленные аргументы приводят к целочисленному результату.
При попытке поделить на значение, равное
0
, мы получим исключение System.DivideByZeroException
в runtime:int i = 0;
int r = 7 / i; // DivideByZeroException
При попытке поделить на литерал
0
мы получим исключение на этапе компиляции:int r = 7 / 0; // Division by constant zero
💬 Тем удивительнее оказывается тот факт, что в случае деления числа с плавающей точкой на ноль (
1.0 / 0
) вышеупомянутое исключение выброшено не будет. Мы просто получим в результате бесконечность (Infinity
) 🙂#basics
Округление чисел с плавающей точкой в C#
Во время разработки мы временами сталкиваемся с необходимостью округлить число с плавающей точкой типа
Поэтому в дело вступает явное приведение:
Однако, с этим кодом всё не так просто. Дело в том, что подобное округление на деле окажется ничем иным, как отбрасыванием дробной части у целочисленного значения.
Если же мы хотим руководствоваться математическими правилами округления, то с этим нам поможет класс System.Convert:
Но и здесь всё не всегда так гладко 😅 Оказывается, в .NET алгоритм округления (banker's rounding) отличается от привычного нам в тех случаях, когда значения являются пограничными: 0.5, 3.5. В этих случаях округление осуществляется в пользу ближайшего чётного:
💬 Заинтересованы алгоритмом и причиной подобного решения в .NET? Подробнее почитать об этом вы сможете уже самостоятельно здесь 😉
#basics
Во время разработки мы временами сталкиваемся с необходимостью округлить число с плавающей точкой типа
float
или double
к целочисленному значению типа int
. Сделать это неявно, как я уже упоминал ранее, у нас не получится ввиду отсутствия реализации подобного приведения:int n1 = 4.8f; // Cannot implicitly convert
Поэтому в дело вступает явное приведение:
int n1 = (int)4.8f;
Однако, с этим кодом всё не так просто. Дело в том, что подобное округление на деле окажется ничем иным, как отбрасыванием дробной части у целочисленного значения.
Если же мы хотим руководствоваться математическими правилами округления, то с этим нам поможет класс System.Convert:
float f1 = 4.8f;
int n1 = Convert.ToInt32(4.8f); // 5
Но и здесь всё не всегда так гладко 😅 Оказывается, в .NET алгоритм округления (banker's rounding) отличается от привычного нам в тех случаях, когда значения являются пограничными: 0.5, 3.5. В этих случаях округление осуществляется в пользу ближайшего чётного:
int n1 = Convert.ToInt32(8.5f); // 8
int n2 = Convert.ToInt32(9.5f); // 10
💬 Заинтересованы алгоритмом и причиной подобного решения в .NET? Подробнее почитать об этом вы сможете уже самостоятельно здесь 😉
#basics