Українська
Логічні операції та клас Math
Порівняння, логічні та побітові операції
Операції порівняння
Операції == (дорівнює), != (не дорівнює), <, >, <=, >= порівнюють значення та повертають bool. Не плутайте операцію порівняння == з присвоюванням =. Для дійсних чисел пам’ятайте про похибку (див. вище) (https://learn.microsoft.com/dotnet/csharp/language-reference/operators/comparison-operators).
Логічні операції
Логічні операції виконуються над значеннями bool (https://learn.microsoft.com/dotnet/csharp/language-reference/operators/boolean-logical-operators):
!a– логічне НЕ (заперечення);a && b– умовне логічне І:true, якщо обидва операндиtrue;a || b– умовне логічне АБО:true, якщо хоча б один операндtrue;a ^ b– виключне АБО:true, якщо операнди різні;a & b,a | b– логічні І та АБО, які завжди обчислюють обидва операнди.
Операції && і || виконують скорочене обчислення (short-circuit evaluation): правий операнд не обчислюється, якщо результат уже відомий з лівого. Це дозволяє безпечно записувати умови, де друга частина має сенс лише за виконання першої:
cs
int count = 0, total = 10, age = 19, day = 6;
bool ok = count != 0 && total / count > 1; // False, ділення немає
bool isAdult = age >= 18 && age < 120; // True
bool isWeekend = day == 6 || day == 7; // TrueПобітові операції та зсуви
Побітові операції працюють з окремими бітами цілих чисел (табл. 2.6). Їх використовують для прапорців і масок, упакування кількох значень в одне число, швидкого множення й ділення на степені двійки (https://learn.microsoft.com/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators).
Таблиця 2.6. Побітові операції та зсуви
| Операція | Назва | Приклад | Результат |
|---|---|---|---|
& | побітове І | 0b1100 & 0b1010 | 0b1000 (8) |
| | побітове АБО | 0b1100 | 0b1010 | 0b1110 (14) |
^ | побітове виключне АБО | 0b1100 ^ 0b1010 | 0b0110 (6) |
~ | побітове доповнення | ~5 | −6 |
<< | зсув ліворуч | 1 << 10 | 1024 |
>> | арифметичний зсув праворуч | -16 >> 2 | −4 |
>>> | логічний зсув праворуч | -16 >>> 2 | 1 073 741 820 |
Зсув ліворуч на n бітів множить число на 2n, зсув праворуч – ділить. Операція >> для знакових типів зберігає знак (заповнює старші біти знаковим бітом), а >>> заповнює їх нулями. Типові дії з маскою (mask) – числом, у якому одиницями позначено потрібні біти:
cs
const int Read = 0b100, Write = 0b010, Execute = 0b001;
int rights = Read | Write; // встановити біти: 0b110
bool canWrite = (rights & Write) != 0; // перевірити біт: True
rights &= ~Write; // скинути біт: 0b100
rights ^= Execute; // перемкнути біт: 0b101Пріоритет і асоціативність операцій
Операції виконуються в порядку пріоритету (табл. 2.7): у виразі 2 + 3 * 4 спочатку виконується множення, результат – 14. Операції з однаковим пріоритетом виконуються зліва направо (лівоасоціативні): 10 - 4 - 3 дорівнює 3. Виняток – присвоювання, ?? і ?:, які виконуються справа наліво: a = b = 0 спочатку присвоює 0 змінній b (https://learn.microsoft.com/dotnet/csharp/language-reference/operators/#operator-precedence).
Таблиця 2.7. Пріоритет операцій C#
| Група (від вищого пріоритету) | Операції |
|---|---|
| первинні | x.y, f(x), a[i], x++, x--, checked, default, new |
| унарні | +x, -x, !x, ~x, ++x, --x, (T)x |
| мультиплікативні | *, /, % |
| адитивні | +, - |
| зсуви | <<, >>, >>> |
| відношення | <, >, <=, >=, is, as |
| рівність | ==, != |
| побітові й логічні | &, потім ^, потім | |
| умовні логічні | &&, потім || |
| об’єднання з null | ?? |
| умовна операція | ?: |
| присвоювання | =, +=, -=, *=, /=, %=, &=, |=, ^=, ??= |
Операції порівняння мають вищий пріоритет, ніж &, ^ і |. Тому вираз flags & mask != 0 компілятор розуміє як flags & (mask != 0) і повідомляє про помилку CS0019. Не запам’ятовуйте всю таблицю: у складних виразах ставте дужки, вони роблять порядок обчислення очевидним.
Клас Math і випадкові числа
Статичний клас Math містить математичні константи й функції (табл. 2.8). Тригонометричні функції приймають кути в радіанах (https://learn.microsoft.com/dotnet/api/system.math).
Таблиця 2.8. Основні члени класу Math
| Метод, константа | Призначення та приклад |
|---|---|
Math.PI, Math.E | числа π = 3,14159… та e = 2,71828… |
Math.Abs(x) | модуль: Math.Abs(-5) – 5 |
Math.Pow(x, y) | степінь: Math.Pow(2, 10) – 1024 (тип double) |
Math.Sqrt(x), Math.Cbrt(x) | квадратний і кубічний корені: Math.Cbrt(27) – 3 |
Math.Round(x) | округлення до цілого: Math.Round(2.5) – 2, Math.Round(3.5) – 4 |
Math.Round(x, n) | округлення до n знаків: Math.Round(1.23456, 2) – 1,23 |
Math.Ceiling(x) | округлення вгору: Math.Ceiling(2.1) – 3 |
Math.Floor(x) | округлення вниз: Math.Floor(-2.1) – −3 |
Math.Truncate(x) | відкидання дробової частини: Math.Truncate(-2.7) – −2 |
Math.Min(a, b), Math.Max(a, b) | менше й більше з двох чисел |
Math.Clamp(x, min, max) | обмеження діапазоном: Math.Clamp(15, 0, 10) – 10 |
Math.Sin(x), Math.Cos(x) | синус і косинус кута в радіанах |
Math.Log(x), Math.Log10(x) | натуральний і десятковий логарифми |
Режими округлення
Метод Math.Round за замовчуванням використовує банківське округлення (MidpointRounding.ToEven): число, що лежить точно посередині, округлюється до найближчого парного. Тому Math.Round(2.5) дорівнює 2, а Math.Round(3.5) – 4. Такий режим зменшує накопичення похибки під час підсумовування багатьох округлених значень. Звичне шкільне округлення «від нуля» задають параметром MidpointRounding.AwayFromZero (https://learn.microsoft.com/dotnet/api/system.midpointrounding):
cs
var away = MidpointRounding.AwayFromZero;
Console.WriteLine(Math.Round(2.5)); // 2
Console.WriteLine(Math.Round(2.5, away)); // 3
Console.WriteLine(Math.Round(2.345m, 2)); // 2,34
Console.WriteLine(Math.Round(2.345m, 2, away)); // 2,35Для double результат округлення до знаків після коми може бути неочікуваним, бо саме число зберігається неточно. Гроші округлюйте в типі decimal.
Випадкові числа
Випадкові числа генерує клас Random. Найпростіше використовувати спільний генератор Random.Shared (https://learn.microsoft.com/dotnet/api/system.random.shared):
cs
int dice = Random.Shared.Next(1, 7); // від 1 до 6
double chance = Random.Shared.NextDouble(); // від 0 до 1 (без 1)
int percent = Random.Shared.Next(101); // від 0 до 100Верхня межа методу Next не входить у діапазон: Next(1, 7) повертає числа від 1 до 6.