Математические функции в C# (Си Шарп)
Почти все математические функции C# собраны в статическом классе System.Math: округление, модуль, степень, корни, логарифмы, тригонометрия и сравнение чисел. Ниже разобрано, как они работают, какие у них подводные камни и какие новые методы появились в .NET 6-8. Каждый пример можно скопировать в консольный проект и запустить.

Содержание
Класс Math и его константы
Класс Math не требует создания объекта и подключения дополнительных пространств имён, достаточно стандартной директивы using System;, которая в новых проектах добавляется автоматически. Рядом существует класс MathF с теми же методами для типа float. Для вычислений с ним сохраняются те же правила, но результаты возвращаются с меньшей точностью. Кроме методов, в классе есть две константы: Math.PI (число пи) и Math.E (основание натурального логарифма). В .NET 5 и новее добавлена ещё Math.Tau, равная 2 пи.
Console.WriteLine(Math.PI); // 3.141592653589793
Console.WriteLine(Math.E); // 2.718281828459045
Console.WriteLine(Math.Tau); // 6.283185307179586
double r = 5;
double circleArea = Math.PI * r * r;
Console.WriteLine($"Площадь круга: {circleArea:F2}"); // 78,54Большинство методов принимает и возвращает double. Для целых и других числовых типов существуют перегрузки не у всех функций, поэтому помните о неявных преобразованиях и о том, что результат вещественной функции придётся приводить к целому вручную.
Основные функции: модуль, знак, минимум и максимум
Эти методы встречаются в каждой второй программе. Math.Abs возвращает модуль числа, Math.Sign - знак (-1, 0 или 1), а Math.Min и Math.Max выбирают меньшее и большее из двух значений. Для ограничения числа диапазоном лучше использовать Math.Clamp, он заменяет пару вложенных вызовов Min и Max.
Console.WriteLine(Math.Abs(-5)); // 5
Console.WriteLine(Math.Sign(-20)); // -1
Console.WriteLine(Math.Max(5, 10)); // 10
Console.WriteLine(Math.Min(5, 10)); // 5
Console.WriteLine(Math.Clamp(150, 0, 100)); // 100
Console.WriteLine(Math.Clamp(-3, 0, 100)); // 0Есть один неочевидный случай: Math.Abs(int.MinValue) бросает OverflowException, потому что положительного аналога у минимального значения int нет. Если данные приходят извне, приведите число к long перед вычислением или проверьте значение заранее.
Округление чисел
Округление - главный источник путаницы. Math.Round по умолчанию применяет банковское округление: значение ровно посередине между двумя целыми округляется к ближайшему чётному. Поэтому 2.5 превращается в 2, а 3.5 - в 4. Чтобы получить школьное правило "от нуля", передайте режим MidpointRounding.AwayFromZero.
Console.WriteLine(Math.Round(2.5)); // 2
Console.WriteLine(Math.Round(3.5)); // 4
Console.WriteLine(Math.Round(2.5, MidpointRounding.AwayFromZero)); // 3
Console.WriteLine(Math.Round(3.14159, 2)); // 3.14
Console.WriteLine(Math.Round(0.125, 2)); // 0.12
Console.WriteLine(Math.Round(0.125, 2, MidpointRounding.AwayFromZero)); // 0.13Остальные функции округляют всегда в одну сторону. Floor идёт вниз, Ceiling вверх, а Truncate отбрасывает дробную часть. Разница заметна на отрицательных числах.
| Значение | Floor | Ceiling | Truncate | Round |
|---|---|---|---|---|
| 3.7 | 3 | 4 | 3 | 4 |
| 3.2 | 3 | 4 | 3 | 3 |
| -3.7 | -4 | -3 | -3 | -4 |
| -3.2 | -4 | -3 | -3 | -3 |
| 2.5 | 2 | 3 | 2 | 2 |
Чтобы вывести число с двумя знаками после запятой, не всегда нужно округлять значение: достаточно формата ToString("F2"). Эти два сценария мы развели в отдельной статье про отображение чисел с двумя знаками. Округление до сотен и тысяч выполняется делением, округлением и умножением: Math.Round(x / 100) * 100.
Целочисленное деление и остаток
Для целых чисел деление и остаток часто нужны вместе. Метод Math.DivRem возвращает оба значения за один вызов, начиная с .NET 6 он отдаёт кортеж. Операция % в C# сохраняет знак делимого, поэтому -7 % 3 равно -1. Если нужен неотрицательный остаток, например для индекса по кругу, прибавьте делитель и снова возьмите остаток.
var (quotient, remainder) = Math.DivRem(17, 5);
Console.WriteLine($"{quotient} и {remainder}"); // 3 и 2
int index = -1;
int size = 5;
int wrapped = ((index % size) + size) % size;
Console.WriteLine(wrapped); // 4Степени, корни и экспонента
Метод Math.Pow(x, y) возводит число в степень, и вся его специфика описана в статье про возведение в степень. Math.Sqrt извлекает квадратный корень, Math.Cbrt - кубический. Для отрицательного аргумента Sqrt возвращает NaN, а не бросает исключение, поэтому проверяйте данные заранее. Math.Exp(x) вычисляет число e в степени x.
Console.WriteLine(Math.Sqrt(9)); // 3
Console.WriteLine(Math.Sqrt(-1)); // NaN
Console.WriteLine(Math.Cbrt(27)); // 3
Console.WriteLine(Math.Exp(1)); // 2.718281828459045
Console.WriteLine(Math.Pow(2, 10)); // 1024
// длина вектора (теорема Пифагора)
double a = 3, c = 4;
Console.WriteLine(Math.Sqrt(a * a + c * c)); // 5Логарифмы
В классе есть натуральный логарифм Math.Log(x), десятичный Math.Log10(x) и двоичный Math.Log2(x). Для произвольного основания используется перегрузка Math.Log(x, base). Логарифм нуля равен минус бесконечности, а логарифм отрицательного числа - NaN. Типичные применения: определение количества цифр числа, количества бит и расчёт глубины дерева.
Console.WriteLine(Math.Log(Math.E)); // 1
Console.WriteLine(Math.Log10(1000)); // 3
Console.WriteLine(Math.Log2(1024)); // 10
Console.WriteLine(Math.Log(81, 3)); // 4
int number = 12345;
int digits = (int)Math.Floor(Math.Log10(number)) + 1;
Console.WriteLine(digits); // 5Приём с подсчётом цифр работает для положительных чисел. Для нуля и отрицательных значений нужна отдельная обработка, иначе получите бесконечность или NaN.
Тригонометрия
Функции Sin, Cos, Tan принимают угол в радианах, а не в градусах. Это самая частая ошибка: Math.Sin(90) не равно единице. Переводите градусы формулой радианы = градусы * Math.PI / 180. Обратные функции Asin, Acos, Atan возвращают радианы. Для вычисления угла по координатам существует Math.Atan2(y, x), он правильно определяет четверть и не делит на ноль.
static double ToRadians(double degrees) => degrees * Math.PI / 180;
static double ToDegrees(double radians) => radians * 180 / Math.PI;
double angle = ToRadians(30);
Console.WriteLine(Math.Sin(angle)); // 0.49999999999999994
Console.WriteLine(Math.Round(Math.Sin(angle), 6)); // 0.5
Console.WriteLine(ToDegrees(Math.Atan2(1, 1))); // 45
Console.WriteLine(Math.Cos(Math.PI / 2)); // 6.123233995736766E-17, а не 0Обратите внимание на результаты: из-за двоичного представления чисел значения вроде 0.49999999999999994 и 6.1E-17 отличаются от идеальных. Сравнивать такие числа через == нельзя, используйте допуск или округление. Причины подробно объяснены в статье почему вещественные числа неточны. Заодно в .NET 7 появились методы double.DegreesToRadians и double.RadiansToDegrees, которые можно использовать вместо собственных функций.
Гиперболические функции Sinh, Cosh, Tanh и обратные им Asinh, Acosh, Atanh нужны реже, в основном в научных расчётах и активационных функциях нейронных сетей.
Проверка результата на корректность
Математические методы редко бросают исключения. Вместо этого они возвращают NaN или бесконечность, и неверное значение молча попадает в дальнейшие расчёты. Любая операция с NaN даёт NaN, а сравнение NaN с чем угодно, даже с самим собой, возвращает false. Для проверки используйте специальные методы типа double.
double x = Math.Sqrt(-4);
Console.WriteLine(double.IsNaN(x)); // True
Console.WriteLine(x == double.NaN); // False, так сравнивать нельзя
Console.WriteLine(double.IsInfinity(Math.Log(0))); // True
Console.WriteLine(double.IsFinite(5.0)); // TrueСводная таблица методов
| Метод | Что делает | Пример |
|---|---|---|
| Abs | модуль числа | Math.Abs(-7) = 7 |
| Sign | знак числа | Math.Sign(-3.5) = -1 |
| Min, Max | меньшее, большее | Math.Max(2, 9) = 9 |
| Clamp | ограничение диапазоном | Math.Clamp(12, 0, 10) = 10 |
| Round | округление | Math.Round(2.567, 1) = 2.6 |
| Floor, Ceiling | вниз, вверх | Math.Ceiling(4.1) = 5 |
| Truncate | отбрасывание дробной части | Math.Truncate(-4.9) = -4 |
| Sqrt, Cbrt | корень квадратный, кубический | Math.Sqrt(16) = 4 |
| Pow | степень | Math.Pow(2, 5) = 32 |
| Exp | e в степени x | Math.Exp(0) = 1 |
| Log, Log10, Log2 | логарифмы | Math.Log10(100) = 2 |
| Sin, Cos, Tan | тригонометрия в радианах | Math.Cos(0) = 1 |
| Atan2 | угол по координатам | Math.Atan2(1, 1) = 0.785 |
| DivRem | частное и остаток | Math.DivRem(17, 5) = (3, 2) |
Функции для decimal и обобщённая математика
Для финансовых расчётов на типе decimal доступны не все методы: у него есть перегрузки Abs, Round, Floor, Ceiling, Truncate, Min, Max, Sign, но нет тригонометрии, логарифмов и степени. Когда нужны такие операции, придётся переходить на double и учитывать потерю десятичной точности. Критерии выбора типа разбираются в материале decimal против double.
Начиная с .NET 7 появилась обобщённая математика: интерфейсы INumber<T>, IFloatingPoint<T> и другие позволяют написать один метод для любого числового типа. Многие функции доступны и как статические методы самих типов: int.Abs, double.Sqrt, double.Clamp, int.Log2.
using System.Numerics;
static T Average<T>(IEnumerable<T> items) where T : INumber<T>
{
T sum = T.Zero;
int count = 0;
foreach (var item in items)
{
sum += item;
count++;
}
return sum / T.CreateChecked(count);
}
Console.WriteLine(Average(new[] { 1, 2, 3, 4 })); // 2
Console.WriteLine(Average(new[] { 1.5, 2.5, 3.5 })); // 2,5Заметьте, что для целых чисел результат деления тоже целый, как объяснено в статье о целочисленном делении. Для среднего значения целых чисел вычисляйте сумму в double.
Типичные ошибки
- Подача градусов в тригонометрические функции вместо радиан.
- Сравнение вещественных результатов через
==без допуска. - Ожидание школьного округления от
Math.Round: без параметра он округляет до чётного. - Деление целых чисел там, где нужен дробный результат:
1 / 2равно нулю. - Приведение результата к
intбез проверки диапазона и без предварительного округления. - Игнорирование NaN и бесконечности после
Sqrt,Logи деления на ноль.
Частые вопросы
Какой класс отвечает за математику в C#?
Статический класс System.Math. Для типа float есть MathF, для больших целых - System.Numerics.BigInteger, а для обобщённых вычислений интерфейсы INumber<T> и родственные.
Почему Math.Round(2.5) возвращает 2?
По умолчанию действует банковское округление к чётному. Чтобы получить 3, передайте MidpointRounding.AwayFromZero.
Как вычислить синус угла в градусах?
Переведите градусы в радианы: Math.Sin(градусы * Math.PI / 180). Сами методы Sin, Cos и Tan принимают только радианы.
Как извлечь корень n-й степени?
Используйте Math.Pow(x, 1.0 / n) для положительных чисел. Для квадратного корня применяйте Math.Sqrt, для кубического Math.Cbrt. Запись 1 / n с целыми числами даст ноль, поэтому пишите 1.0 / n.
Как получить случайное число и есть ли оно в Math?
В классе Math генератора нет. Случайные числа создаются классом Random, подробности в статье про случайные числа в C#.
Что вернёт Math.Sqrt от отрицательного числа?
Значение double.NaN. Исключение не бросается, поэтому результат нужно проверять через double.IsNaN.





