Арифметические операции. Операторы отношения и логические операторы

В этом разделе кратко описаны синтаксис и применение всех операций C#, кроме некоторых первичных, которые рассматриваются позже при изучении соответствующего материала.

Инкремент и декремент

Операции инкремента (++) и декремента (--) увеличивают и уменьшают операнд на единицу. Они имеют две формы записи - префиксную , когда знак операции записывается перед операндом, и постфиксную . В префиксной форме сначала изменяется операнд, а затем его значение становится результирующим значением выражения, а в постфиксной форме значением выражения является исходное значение операнда, после чего он изменяется.

Стандартные операции инкремента существуют для целых, символьных, вещественных и финансовых величин.

Операция new

Операция new служит для создания нового объекта. Формат операции:

new тип ([ аргументы ])

С помощью этой операции можно создавать объекты как ссылочных, так и значимых типов, например:

object z = new object(); int i = new int(); // то же самое, что int i = 0;

При выполнении операции new сначала выделяется необходимый объем памяти (для ссылочных типов в хипе, для значимых - в стеке), а затем вызывается так называемый конструктор по умолчанию , то есть метод, с помощью которого инициализируется объект. Переменной значимого типа присваивается значение по умолчанию , которое равно нулю соответствующего типа.

Операции отрицания

Арифметическое отрицание (унарный минус – ) меняет знак операнда на противоположный. Стандартная операция отрицания определена для типов int , long , float , double и decimal . К величинам других типов ее можно применять, если для них возможно неявное преобразование к этим типам.

Логическое отрицание (!) определено для типа bool . Результат операции - значение false , если операнд равен true , и значение true , если операнд равен false .

Поразрядное отрицание (~ ), часто называемое побитовым, инвертирует каждый разряд в двоичном представлении операнда типа int , uint , long или ulong .

Явное преобразование типа

Операция используется для явного преобразования величины из одного типа в другой. Это требуется в том случае, когда неявного преобразования не существует. При преобразовании из более длинного типа в более короткий возможна потеря информации. Формат операции:

(тип) выражение

Здесь тип - это имя того типа, в который осуществляется преобразование, а выражение чаще всего представляет собой имя переменной, например:

long b = 300; int a = (int) b; // данные не теряются int d = (byte) a; // данные теряются

Умножение, деление и остаток от деления

Операция умножения (* ) возвращает результат перемножения двух операндов. Стандартная операция умножения определена для типов int , uint , long , ulong , float , double и decimal . К величинам других типов ее можно применять, если для них возможно неявное преобразование к этим типам. Тип результата операции равен "наибольшему" из типов операндов, но не менее int .

таблице 3.2 . Символами х и y обозначены конечные положительные значения, символом z - результат операции вещественного умножения. Если результат слишком велик для представления с помощью заданного типа, он принимается равным значению "бесконечность", если слишком мал, он принимается за 0. NaN (not a number) означает, что результат не является числом.

Таблица 3.2. Результаты вещественного умножения
* +y -y +0 -0 + - NaN
+x +z -z +0 -0 + - NaN
-x -z +z -0 +0 - + NaN
+0 +0 -0 +0 -0 NaN NaN NaN
-0 -0 +0 -0 +0 NaN NaN NaN
+ + - NaN NaN + - NaN
- - + NaN NaN - + NaN
NaN NaN NaN NaN NaN NaN NaN NaN

Операция деления (/ ) вычисляет частное от деления первого операнда на второй. Стандартная операция деления определена для типов int , uint , long , ulong , float , double и decimal . К величинам других типов ее можно применять, если для них существует неявное преобразование к этим типам. Тип результата определяется правилами преобразования, но не меньше int .

Если оба операнда целочисленные, результат операции округляется вниз до ближайшего целого числа. Если делитель равен нулю, генерируется исключение System.DivideByZeroException .

Если хотя бы один из операндов вещественный, дробная часть результата деления не отбрасывается, а все возможные значения приведены в таблице 3.3 .

Таблица 3.3. Результаты вещественного деления
/ +y -y +0 -0 + - NaN
+x +z -z + - +0 -0 NaN
-x -z +z - + -0 +0 NaN
+0 +0 -0 NaN NaN +0 -0 NaN
-0 -0 +0 NaN NaN -0 +0 NaN
+ + - + - NaN NaN NaN
- - + - + NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN

Для финансовых величин (тип decimal ) при делении на 0 и переполнении генерируются соответствующие исключения, при исчезновении порядка результат равен 0.

Операция остатка от деления (% ) также интерпретируется по-разному для целых, вещественных и финансовых величин. Если оба операнда целочисленные, результат операции вычисляется по формуле x - (x / y) * y . Если делитель равен нулю, генерируется исключение System.DivideByZeroException .

Если хотя бы один из операндов вещественный, результат операции вычисляется по формуле x – n * y , где n - наибольшее целое, меньшее или равное результату деления х на y . Все возможные комбинации значений операндов приведены в таблице 3.4 .

Таблица 3.4. Результаты вещественного остатка от деления
% +y -y +0 -0 + - NaN
+x +z z NaN NaN x x NaN
-x -z -z NaN NaN -x -x NaN
+0 +0 +0 NaN NaN +0 +0 NaN
-0 -0 -0 NaN NaN -0 -0 NaN
+ NaN NaN NaN NaN NaN NaN NaN
- NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN

Для финансовых величин (тип decimal ) при получении остатка от деления на 0 и при переполнении генерируются соответствующие исключения, при исчезновении порядка результат равен 0. Знак результата равен знаку первого операнда.

Сложение и вычитание

Операция сложения (+ ) возвращает сумму двух операндов. Стандартная операция сложения определена для типов int , uint , long , ulong , float , double и decimal . К величинам других типов ее можно применять, если для них существует неявное преобразование к этим типам. Тип результата операции равен "наибольшему" из типов операндов, но не менее int .

Все возможные значения для вещественных операндов приведены в таблице 3.5 .

Таблица 3.5. Результаты вещественного сложения
+ y +0 -0 + - NaN
x z x x + - NaN
+0 y +0 +0 + - NaN
-0 y +0 -0 + - NaN
+ + + + + NaN NaN
- - - - NaN - NaN
NaN NaN NaN NaN NaN NaN NaN

Операция вычитания (- ) возвращает разность двух операндов. Стандартная операция вычитания определена для типов int , uint , long , ulong , float , double и decimal . К величинам других типов ее можно применять, если для них существует неявное преобразование к этим типам. Тип результата операции равен "наибольшему" из типов операндов, но не менее int .

Если оба операнда целочисленные или типа decimal и результат операции слишком велик для представления с помощью заданного типа, генерируется исключение System.OverflowException .

Все возможные значения результата вычитания для вещественных операндов приведены в таблице 3.6 . Символами х и y обозначены конечные положительные значения, символом z - результат операции вещественного вычитания. Если х и y равны, результат равен положительному нулю. Если результат слишком велик для представления с помощью заданного типа, он принимается равным значению "бесконечность" с тем же знаком, что х - y , если слишком мал, он принимается за 0 с тем же знаком, что х - y .

Таблица 3.6. Результаты вещественного вычитания
- y +0 -0 + - NaN
x z x x - + NaN
+0 -y +0 +0 - + NaN
-0 -y -0 +0 - + NaN
+ + + + NaN + NaN
- - - - - NaN NaN
NaN NaN NaN NaN NaN NaN NaN

Операции сдвига

Операции сдвига (<< и >> ) применяются к целочисленным операндам. Они сдвигают двоичное представление первого операнда влево или вправо на количество двоичных разрядов, заданное вторым операндом.

При сдвиге влево (<< ) освободившиеся разряды обнуляются. При сдвиге вправо (>> ) освободившиеся биты заполняются нулями, если первый операнд беззнакового типа, и знаковым разрядом в противном случае. Стандартные операции сдвига определены для типов int , uint , long и ulong .

Операции отношения и проверки на равенство

Операции отношения (< , <= , > , >= , == , != ) сравнивают первый операнд со вторым. Операнды должны быть арифметического типа. Результат операции - логического типа, равен true или false . Правила вычисления результатов приведены в > y

true , если x больше y , иначе false x <= y true , если x меньше или равно y , иначе false x >= y true , если x больше или равно y , иначе false

Поразрядные логические операции

Поразрядные логические операции (& , | , ^ ) применяются к целочисленным операндам и работают с их двоичными представлениями. При выполнении операций операнды сопоставляются побитно (первый бит первого операнда с первым битом второго, второй бит первого операнда со вторым битом второго, и т д.). Стандартные операции определены для типов int , uint , long и ulong .

При поразрядной конъюнкции (& ), бит результата равен 1 только тогда, когда соответствующие биты обоих операндов равны 1.

При поразрядной дизъюнкции (| ), бит результата равен 1 тогда, когда соответствующий бит хотя бы одного из операндов равен 1.

При поразрядном исключающем ИЛИ () бит результата равен 1 только тогда, когда соответствующий бит только одного из операндов равен 1.

Условные логические операции

Условные логические операции И (&& ) и ИЛИ (|| ) чаще всего используются с операндами логического типа. Результатом логической операции является true true , то результатом условной операции будет значение второго операнда, иначе - третьего операнда. Вычисляется всегда либо второй операнд, либо третий. Их тип может различаться.

Тип результата операции зависит от типа второго и третьего операндов. Если операнды одного типа, он и становится типом результата операции.

Операции присваивания

Операции присваивания (= , += , -= , *= и т. д.) задают новое значение переменной. Эти операции могут использоваться в программе как законченные операторы.

Формат операции простого присваивания (= ):

переменная = выражение

Механизм выполнения операции присваивания такой: вычисляется выражение и его результат заносится в память по адресу, который определяется именем переменной, находящейся слева от знака операции. То, что ранее хранилось в этой области памяти, теряется. Примеры операторов присваивания:

сложении с присваиванием ко второму операнду прибавляется первый, и результат записывается в первый операнд, то есть выражение a += b является более компактной записью выражения a = a + b .

Результатом операции сложного присваивания является значение, записанное в левый операнд.

Операции присваивания правоассоциативны , то есть выполняются справа налево, в отличие от большинства других операций (a = b = c означает a = (b = c) ).

Вопросы и задания для самостоятельной работы студента

  1. Где можно описывать переменные? Что входит в описание переменной?
  2. Что происходит при использовании в выражении операндов различных типов? Приведите примеры.
  3. Перечислите операции языка C#, сгруппировав их по приоритетам.
  4. Что такое NaN? В каких операциях NaN является результатом?
  5. К операндам какого типа применимы операции сдвига?
  6. Что такое исключительные ситуации?
  7. Опишите принципы обработки исключительных ситуаций.

Операторы отношения и логические операторы

В обозначениях оператор отношения и логический оператор термин отношения означает взаимосвязь, которая может существовать между двумя значениями, а термин логический - взаимосвязь между логическими значениями "истина" и "ложь". И поскольку операторы отношения дают истинные или ложные результаты, то они нередко применяются вместе с логическими операторами. Именно по этой причине они и рассматриваются совместно.

Ниже перечислены операторы отношения:

К числу логических относятся операторы, приведенные ниже:

Результатом выполнения оператора отношения или логического оператора является логическое значение типа bool .

В целом, объекты можно сравнивать на равенство или неравенство, используя операторы отношения == и!=. А операторы сравнения, = могут применяться только к тем типам данных, которые поддерживают отношение порядка. Следовательно, операторы отношения можно применять ко всем числовым типам данных. Но значения типа bool могут сравниваться только на равенство или неравенство, поскольку истинные (true) и ложные (false) значения не упорядочиваются. Например, сравнение true > false в C# не имеет смысла.

Рассмотрим пример программы, демонстрирующий применение операторов отношения и логических операторов:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string args) { short d = 10, f = 12; bool var1 = true, var2 = false; if (d f) Console.WriteLine("d > f"); // Сравниванием переменные var1 и var2 if (var1 & var2) Console.WriteLine("Данный текст не выведется"); if (!(var1 & var2)) Console.WriteLine("!(var1 & var2) = true"); if (var1 | var2) Console.WriteLine("var1 | var2 = true"); if (var1 ^ var2) Console.WriteLine("var1 ^ var2 = true"); Console.ReadLine(); } } }

Логические операторы в C# выполняют наиболее распространенные логические операции. Тем не менее существует ряд операций, выполняемых по правилам формальной логики. Эти логические операции могут быть построены с помощью логических операторов, поддерживаемых в C#. Следовательно, в C# предусмотрен такой набор логических операторов, которого достаточно для построения практически любой логической операции, в том числе импликации. Импликация - это двоичная операция, результатом которой является ложное значение только в том случае, если левый ее операнд имеет истинное значение, а правый - ложное. (Операция импликации отражает следующий принцип: истина не может подразумевать ложь.)

Операция импликации может быть построена на основе комбинации логических операторов! и |:

Укороченные логические операторы

В C# предусмотрены также специальные, укороченные , варианты логических операторов И и ИЛИ, предназначенные для получения более эффективного кода. Поясним это на следующих примерах логических операций. Если первый операнд логической операции И имеет ложное значение (false), то ее результат будет иметь ложное значение независимо от значения второго операнда. Если же первый операнд логической операции ИЛИ имеет истинное значение (true), то ее результат будет иметь истинное значение независимо от значения второго операнда. Благодаря тому что значение второго операнда в этих операциях вычислять не нужно, экономится время и повышается эффективность кода .

Укороченная логическая операция И выполняется с помощью оператора && , а укороченная логическая операция ИЛИ - с помощью оператора || . Этим укороченным логическим операторам соответствуют обычные логические операторы & и |. Единственное отличие укороченного логического оператора от обычного заключается в том, что второй его операнд вычисляется только по мере необходимости.

Последнее обновление: 19.06.2017

В C# используется большинство операций, которые применяются и в других языках программирования. Операции представляют определенные действия над операндами - участниками операции. В качестве операнда может выступать переменной или какое-либо значение (например, число). Операции бывают унарными (выполняются над одним операндом), бинарными - над двумя операндами и тернарными - выполняются над тремя операндами. Рассмотрим все виды операций.

Бинарные арифметические операции:

    Операция сложения двух чисел:

    Int x = 10; int z = x + 12; // 22

    Операция вычитания двух чисел:

    Int x = 10; int z = x - 6; // 4

    Операция умножения двух чисел:

    Int x = 10; int z = x * 5; // 50

    операция деления двух чисел:

    Int x = 10; int z = x / 5; // 2 double a = 10; double b = 3; double c = a / b; // 3.33333333

    При делении стоит учитывать, что если оба операнда представляют целые числа, то результат также будет округляться до целого числа:

    Double z = 10 / 4; //результат равен 2

    Несмотря на то, что результат операции в итоге помещается в переменную типа double, которая позволяет сохранить дробную часть, но в самой опеации участвуют два литерала, которые по умолчанию рассматриваются как объекты int, то есть целые числа, и результат то же будет целочисленный.

    Для выхода из этой ситуации необходимо определять литералы или переменные, участвующие в операции, именно как типы double или float:

    Double z = 10.0 / 4.0; //результат равен 2.5

    Операция получение остатка от целочисленного деления двух чисел:

    Double x = 10.0; double z = x % 4.0; //результат равен 2

Также есть ряд унарных операций, в которых принимает участие один операнд:

    Операция инкремента

    Инкремент бывает префиксным: ++x - сначала значение переменной x увеличивается на 1, а потом ее значение возвращается в качестве результата операции.

    И также существует постфиксный инкремент: x++ - сначала значение переменной x возвращается в качестве результата операции, а затем к нему прибавляется 1.

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--).

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}");

При выполнении сразу нескольких арифметических операций следует учитывать порядок их выполнения. Приоритет операций от наивысшего к низшему:

    Инкремент, декремент

    Умножение, деление, получение остатка

    Сложение, вычитание

Для изменения порядка следования операций применяются скобки.

Рассмотрим набор операций:

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, и в конце вычитание. То есть фактически набор операций выглядел так:

Int d = (c--)-(b*a);

Но с помощью скобок мы могли бы изменить порядок операций, например, следующим образом:

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}");

Ассоциативность операторов

Как выше было отмечено, операции умножения и деления имеют один и тот же приоритет, но какой тогда результат будет в выражении:

Int x = 10 / 5 * 2;

Стоит нам трактовать это выражение как (10 / 5) * 2 или как 10 / (5 * 2) ? Ведь в зависимости от трактовки мы получим разные результаты.

Когда операции имеют один и тот же приоритет, порядок вычисления определяется ассоциативностью операторов. В зависимости от ассоциативности есть два типа операторов:

    Левоассоциативные операторы, которые выполняются слева направо

    Правоассоциативные операторы, которые выполняются справа налево

Все арифметические операторы (кроме префиксного инкремента и декремента) являются левоассоциативными, то есть выполняются слева направо. Поэтому выражение 10 / 5 * 2 необходимо трактовать как (10 / 5) * 2 , то есть результатом будет 4.