Программирование L. Унарными (выполняются над одним операндом), бинарными
Скачать 377.23 Kb.
|
Арифметические и логические операции языка C# В C# используется большинство операций, которые применяются и в других языках программирования. Операции представляют определенные действия над операндами - участниками операции. В качестве операнда может выступать переменная или какое-либо значение (например, число). Операции бывают унарными (выполняются над одним операндом), бинарными - над двумя операндами и тернарными - выполняются над тремя операндами. Рассмотрим все виды операций. Бинарные арифметические операции: • + Операция сложения двух чисел: 1 2 int x = 10; int z = x + 12; // 22 • - Операция вычитания двух чисел: 1 2 int x = 10; int z = x - 6; // 4 • * Операция умножения двух чисел: 1 2 int x = 10; int z = x * 5; // 50 • / Операция деления двух чисел: 1 2 3 4 5 6 int x = 10; int z = x / 5; // 2 double a = 10; double b = 3; double c = a / b; // 3.33333333 При делении стоит учитывать, что если оба операнда представляют целые числа, то результат также будет округляться до целого числа: 1 double z = 10 / 4; //результат равен 2 Несмотря на то, что результат операции в итоге помещается в переменную типа double, которая позволяет сохранить дробную часть, но в самой опеации участвуют два литерала, которые по умолчанию Console.WriteLine("{0} {1}", i, j); Console.WriteLine("{0} {1}", ++i, --j); Console.WriteLine("{0} {1}", i++, j--); Console.WriteLine("{0} {1}", i, j); } Результат работы программы: \ 3 4 4 3 4 3 5 2 При выполнении сразу нескольких арифметических операций следует учитывать порядок их выполнения. Приоритет операций от наивысшего к низшему: 1. Инкремент, декремент 2. Умножение, деление, получение остатка 3. Сложение, вычитание Для изменения порядка следования операций применяются скобки. Рассмотрим набор операций: 1 2 3 4 5 int a = 3; int b = 5; int c = 40; int d = c---b*a; // a=3 b=5 c=39 d=25 Console.WriteLine($ "a={a} b={b} c={c} d={d}" ); Здесь мы имеем дело с тремя операциями: декремент, вычитание и умножение. Сначала выполняется декремент переменной c, затем умножение b*a, и в конце вычитание. То есть фактически набор операций выглядел так: 1 int d = (c--)-(b*a); Но с помощью скобок мы могли бы изменить порядок операций, например, следующим образом: 1 2 3 4 5 int a = 3; int b = 5; int c = 40; int d = (c-(--b))*a; // a=3 b=4 c=40 d=108 Console.WriteLine($ "a={a} b={b} c={c} d={d}" ); Ассоциативность операторов Как выше было отмечено, операции умножения и деления имеют один и тот же приоритет, но какой тогда результат будет в выражении: 1 int x = 10 / 5 * 2; Стоит нам трактовать это выражение как (10 / 5) * 2 или как 10 / (5 * 2)? Ведь в зависимости от трактовки мы получим разные результаты. Когда операции имеют один и тот же приоритет, порядок вычисления определяется ассоциативностью операторов. В зависимости от ассоциативности есть два типа операторов: • Левоассоциативные операторы, которые выполняются слева направо • Правоассоциативные операторы, которые выполняются справа налево Все арифметические операторы (кроме префиксного инкремента и декремента) являются левоассоциативными, то есть выполняются слева направо. Поэтому выражение 10 / 5 * 2 необходимо трактовать как (10 / 5) * 2, то есть результатом будет 4. Операции присваивания Операции присвоения устанавливают значение. В операциях присвоения участвуют два операнда, причем левый операнд может представлять только модифицируемое именованное выражение, например, переменную. Как и во многих других языках программирования, в C# имеется базовая операция присваивания =, которая присваивает значение правого операнда левому операнду: 1 int number = 23; Здесь переменной number присваивается число 23. Переменная number представляет левый операнд, которому присваивается значение правого операнда, то есть числа 23. Также можно выполнять множественно присвоение сразу нескольких переменным одновременно: 1 2 int a, b, c; a = b = c = 34; Стоит отметить, что операции присвоения имеют низкий приоритет. И вначале будет вычисляться значение правого операнда и только потом будет идти присвоение этого значения левому операнду. Например: 1 2 int a, b, c; a = b = c = 34 * 2 / 4; // 17 Сначала будет вычисляться выражение 34 * 2 / 4, затем полученное значение будет присвоено переменным. Кроме базовой операции присвоения в C# есть еще ряд операций: • +=: присваивание после сложения. Присваивает левому операнду сумму левого и правого операндов: выражение A += B равнозначно выражению A = A + B • -=: присваивание после вычитания. Присваивает левому операнду разность левого и правого операндов: A -= B эквивалентно A = A - B • *=: присваивание после умножения. Присваивает левому операнду произведение левого и правого операндов: A *= B эквивалентно A = A * B • /=: присваивание после деления. Присваивает левому операнду частное левого и правого операндов: A /= B эквивалентно A = A / B • %=: присваивание после деления по модулю. Присваивает левому операнду остаток от целочисленного деления левого операнда на правый: A %= B эквивалентно A = A % B • &=: присваивание после поразрядной конъюнкции. Присваивает левому операнду результат поразрядной конъюнкции его битового представления с битовым представлением правого операнда: A &= B эквивалентно A = A & B • |=: присваивание после поразрядной дизъюнкции. Присваивает левому операнду результат поразрядной дизъюнкции его битового представления с битовым представлением правого операнда: A |= B эквивалентно A = A | B • ^=: присваивание после операции исключающего ИЛИ. Присваивает левому операнду результат операции исключающего ИЛИ его битового представления с битовым представлением правого операнда: A ^= B эквивалентно A = A ^ B • <<=: присваивание после сдвига разрядов влево. Присваивает левому операнду результат сдвига его битового представления влево на определенное количество разрядов, равное значению правого операнда: A <<= B эквивалентно A = A << B • >>=: присваивание после сдвига разрядов вправо. Присваивает левому операнду результат сдвига его битового представления вправо на определенное количество разрядов, равное значению правого операнда: A >>= B эквивалентно A = A >> B Применение операций присвоения: 1 2 3 4 5 int a = 10; a += 10; // 20 a -= 4; // 16 a *= 2; // 32 a /= 8; // 4 6 7 a <<= 4; // 64 a >>= 2; // 16 Операции присвоения являются правоассоциативными, то есть выполняются справа налево. Например: 1 2 3 int a = 8; int b = 6; int c = a += b -= 5; // 9 В данном случае выполнение выражения будет идти следующим образом: 1. b -= 5 (6-5=1) 2. a += (b-=5) (8+1 = 9) 3. c = (a += (b-=5)) (c = 9) Стандартные математические функции Операторы отношения и логические операторы Отдельный набор операций представляет условные выражения. Такие операции возвращают логическое значение, то есть значение типа bool: true, если выражение истинно, и false, если выражение ложно. К подобным операциям относятся операции сравнения и логические операции. Операции сравнения В операциях сравнения сравниваются два операнда и возвращается значение типа bool - true, если выражение верно, и false, если выражение неверно. • == Сравнивает два операнда на равенство. Если они равны, то операция возвращает true, если не равны, то возвращается false: 1 2 3 int a = 10; int b = 4; bool c = a == b; // false • != Сравнивает два операнда и возвращает true, если операнды не равны, и false, если они равны. 1 2 3 4 int a = 10; int b = 4; bool c = a != b; // true bool d = a!=10; // false • < Операция "меньше чем". Возвращает true, если первый операнд меньше второго, и false, если первый операнд больше второго: 1 2 3 int a = 10; int b = 4; bool c = a < b; // false • > Операция "больше чем". Сравнивает два операнда и возвращает true, если первый операнд больше второго, иначе возвращает false: 1 2 3 4 int a = 10; int b = 4; bool c = a > b; // true bool d = a > 25; // false • <= Операция "меньше или равно". Сравнивает два операнда и возвращает true, если первый операнд меньше или равен второму. Иначе возвращает false. 1 2 3 4 int a = 10; int b = 4; bool c = a <= b; // false bool d = a <= 25; // true • >= Операция "больше или равно". Сравнивает два операнда и возвращает true, если первый операнд больше или равен второму, иначе возвращается false: 1 2 3 4 int a = 10; int b = 4; bool c = a >= b; // true bool d = a >= 25; // false Операции <, > <=, >= имеют больший приоритет, чем == и !=. Логические операции Также в C# определены логические операторы, которые также возвращают значение типа bool. В качестве операндов они принимают значения типа bool. Как правило, применяются к отношениям и объединяют несколько операций сравнения. • | Операция логического сложения или логическое ИЛИ (дизъюнкция). Возвращает true, если хотя бы один из операндов возвращает true. 1 2 bool x1 = (5 > 6) | (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается true bool x2 = (5 > 6) | (4 > 6); // 5 > 6 - false, 4 > 6 - false, поэтому возвращается false • & Операция логического умножения или логическое И (конъюнкция). Возвращает true, если оба операнда одновременно равны true. 1 2 bool x1 = (5 > 6) & (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается false bool x2 = (5 < 6) & (4 < 6); // 5 < 6 - true, 4 < 6 - true, поэтому возвращается true • || Операция логического сложения. Возвращает true, если хотя бы один из операндов возвращает true. 1 2 bool x1 = (5 > 6) || (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается true bool x2 = (5 > 6) || (4 > 6); // 5 > 6 - false, 4 > 6 - false, поэтому возвращается false При использовании оператора ||, если первая операция будет true, то проверка второй операции не выполняется, т.к. true (1) сложить на любое есть true (1). • && Операция логического умножения. Возвращает true, если оба операнда одновременно равны true. 1 2 bool x1 = (5 > 6) && (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается false bool x2 = (5 < 6) && (4 < 6); // 5 < 6 - true, 4 > 6 - true, поэтому возвращается true При использовании оператор &&, если первая операция будет false, то проверка второй операции не выполняется, т.к. false (0) умножить на любое есть false (0). • ! Операция логического отрицания. Производится над одним операндом и возвращает true, если операнд равен false. Если операнд равен true, то операция возвращает false: 1 2 bool a = true ; bool b = !a; // false • ^ Операция исключающего ИЛИ. Возвращает true, если либо первый, либо второй операнд (но не одновременно) равны true, иначе возвращает false 1 2 bool x5 = (5 > 6) ^ (4 < 6); // 5 > 6 - false, 4 < 6 - true, поэтому возвращается true bool x6 = (50 > 6) ^ (4 / 2 < 3); // 50 > 6 - true, 4/2 < 3 - true, поэтому возвращается false Здесь у нас две пары операций | и || (а также & и &&) выполняют похожие действия, однако же они не равнозначны. В выражении z=x|y; будут вычисляться оба значения - x и y. В выражении же z=x||y; сначала будет вычисляться значение x, и если оно равно true, то вычисление значения y уже смысла не имеет, так как у нас в любом случае уже z будет равно true. Значение y будет вычисляться только в том случае, если x равно false То же самое касается пары операций &/&&. В выражении z=x&y; будут вычисляться оба значения - x и y. В выражении же z=x&&y; сначала будет вычисляться значение x, и если оно равно false, то вычисление значения y уже смысла не имеет, так как у нас в любом случае уже z будет равно false. Значение y будет вычисляться только в том случае, если x равно true. Поэтому операции || и && более удобны в вычислениях, так как позволяют сократить время на вычисление значения выражения, и тем самым повышают производительность. А операции | и & больше подходят для выполнения поразрядных операций над числами. Операция && имеет больший приоритет, чем операция ||. Так, в выражении true || true && false сначала выполняется подвыражение true && false. Полный список операций языка C# в соответствии с их приоритетами приведен в следующей таблице. Операция Описание Доступ к элементу x() Вызов метода или делегата x[] Доступ к элементу x++ Постфиксный инкремент x-- Постфиксный декремент new Выделение памяти typeof Получение типа checked Проверяемый код unchecked Непроверяемый код + Унарный плюс - Арифметическое отрицание ! Логическое отрицание Поразрядное отрицание ++x Префиксный инкремент --x Префиксный декремент (тип) x Преобразование типа * Умножение / Деление % Остаток от деления << Сдвиг влево >> Сдвиг вправо < Меньше > Больше <= Меньше или равно >= Больше или равно is Проверка принадлежности типу as Приведение типа == Равно != Не равно & Поразрядное И ^ Поразрядное исключающее ИЛИ | Поразрядное ИЛИ && Логическое И || Логическое ИЛИ ? : Условная операция = Простое присваивание *= Умножение с присваиванием /= Деление с присваиванием %= Остаток от деления с присваиванием += Сложение с присваиванием -= Вычитание с присваиванием <<= Сдвиг влево с присваиванием >>= Сдвиг вправо с присваиванием &= Поразрядное И с присваиванием ^= Поразрядное исключающее ИЛИ с присваиванием |= Поразрядное ИЛИ с присваиванием |
Для выхода из этой ситуации необходимо определять литералы или переменные, участвующие в операции, именно как типы double или float:
1 double z = 10.0 / 4.0;
//результат равен 2.5
•
%
Операция получение остатка от целочисленного деления двух чисел:
1 2 double x = 10.0; double z = x % 4.0;
//результат равен 2
Также есть ряд унарных операций, в которых принимает участие один операнд:
•
++
Операция инкремента
Инкремент бывает префиксным: ++x - сначала значение переменной x увеличивается на 1, а потом ее значение возвращается в качестве результата операции.
И также существует постфиксный инкремент: x++ - сначала значение переменной x возвращается в качестве результата операции, а затем к нему прибавляется 1.
1 2
3 4
5 6
7 int x1 = 5; int z1 = ++x1;
// z1=6; x1=6
Console.WriteLine($
"{x1} - {z1}"
); int x2 = 5; int z2 = x2++;
// z2=5; x2=6
Console.WriteLine($
"{x2} - {z2}"
);
•
--
Операция декремента или уменьшения значения на единицу. Также существует префиксная форма декремента (--x) и постфиксная (x--).
1 2
3 4
5 6
7 int x1 = 5; int z1 = --x1;
// z1=4; x1=4
Console.WriteLine($
"{x1} - {z1}"
); int x2 = 5; int z2 = x2--;
// z2=5; x2=4
Console.WriteLine($
"{x2} - {z2}"
);
Рассмотрим эти операции на примере, static void Main()
{ int i = 3, j = 4;