Статические поля и методы арифметических классов

Все арифметические классы, в том числе класс Int, обладают двумя полезными полями (свойствами) - MinValue и MaxValue. Эти поля возвращают минимальное и максимальное значение, которое могут иметь экземпляры класса. Поля являются статическими и потому недоступны для экземпляров класса и могут быть вызваны только при указании имени класса. Разумно привести пример вызова этих полей для класса Int и, например, для класса Double:

//Min и Max значения типов

Console.WriteLine("Class int");

Console.WriteLine("Мин. значение int = " + int.MinValue);

Console.WriteLine("Макс. значение int = " + int.MaxValue);

Console.WriteLine("Class double");

Console.WriteLine("Мин. значение double = " + double.MinValue);

Console.WriteLine("Макс. значение double = " + double.MaxValue);

Все арифметические классы, в том числе класс Int, обладают перегруженным статическим методом Parse, у которого первым обязательным параметром является строка, задающая значение соответствующего арифметического типа в привычной для данного региона (локализованной) форме. Форматом строки и стилем ее представления можно управлять с помощью других параметров метода Parse. Вот пример вызова этого метода для классов Int и Double:

/// <summary>

/// Преобразования типа с использованием метода Parse

/// </summary>

public void Parsing()

{

//method Parse

Console.WriteLine("Введите целое");

string strdata = Console.ReadLine();

int intdata = int.Parse(strdata);

Console.WriteLine("Введите число с дробной частью и порядком");

strdata = Console.ReadLine();

double doubdata = double.Parse(strdata);

Console.WriteLine("intdata = {0}; doubdata = {1}",

intdata, doubdata);

}

//Parsing

Как видите, метод Parse с успехом заменяет соответствующий метод класса Convert.

На рис. 6.3 можно увидеть консольный вывод, полученный в результате работы процедуры Parsing.

Статические поля и методы арифметических классов - student2.ru

Рис. 6.3.Результаты работы процедуры Parsing

Операция new

Пора вернуться к основной теме - операциям, допустимым в языке C#. Последней из еще не рассмотренных операций высшего уровня приоритета является операция new. Ключевое слово new используется в двух контекстах - как модификатор и как операция в инициализирующих выражениях объявителя. Во втором случае результатом выполнения операции new является создание нового объекта и вызов соответствующего конструктора. Примеров подобного использования операции new было приведено достаточно много, в том числе и в этой лекции.

Арифметические операции

В языке C# имеются обычные для всех языков арифметические операции - " +, -, *, /, % ". Все они перегружены. Операции " + " и " - " могут быть унарными и бинарными. Операция деления " / " над целыми типами осуществляет деление нацело, для типов с плавающей и фиксированной точкой - обычное деление. Операция " % " определена над всеми арифметическими типами и возвращает остаток от деления нацело. Тип результата зависит от типов операндов. Приведу пример вычислений с различными арифметическими типами:

/// <summary>

/// Арифметические операции

/// </summary>

public void Ariphmetica()

{

int n = 7,m =3, p,q;

p= n/m; q= p*m + n%m;

if (q==n) Console.WriteLine("q=n");

else Console.WriteLine("q!=n");

double x=7, y =3, u,v,w;

u = x/y; v= u*y;

w= x%y;

if (v==x) Console.WriteLine("v=x");

else Console.WriteLine("v!=x");

decimal d1=7, d2 =3, d3,d4,d5;

d3 = d1/d2; d4= d3*d2;

d5= d1%d2;

if (d4==d1) Console.WriteLine("d4=d1");

else Console.WriteLine("d4!=d1");

}//Ariphmetica

При проведении вычислений в первых двух случаях проверяемое условие оказалось истинным, в третьем - ложным. Для целых типов можно исходить из того, что равенство n = n/m*m + n%m истинно. Для типов с плавающей точкой выполнение точного равенства x = x/y*y следует считать скорее случайным, а не закономерным событием. Законно невыполнение этого равенства, как это имеет место при вычислениях с фиксированной точкой.

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

Операции отношения можно просто перечислить - в объяснениях они не нуждаются. Всего операций 6 ( ==, !=, <, >, <=, >= ). Для тех, кто не привык работать с языком C++, стоит обратить внимание на запись операций "равно" и "не равно".

Операции проверки типов

Операции проверки типов is и as будут рассмотрены в последующих лекциях. (см. лекцию 19).

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

Операции сдвига вправо " >> " и сдвига влево " << " в обычных вычислениях применяются редко. Они особенно полезны, если данные рассматриваются как строка битов. Результатом операции является сдвиг строки битов влево или вправо на K разрядов. В применении к обычным целым положительным числам сдвиг вправо равносилен делению нацело на 2K, а сдвиг влево - умножению на 2K. Для отрицательных чисел сдвиг влево и деление дают разные результаты, отличающиеся на единицу. В языке C# операции сдвига определены только для некоторых целочисленных типов - int, uint, long, ulong. Величина сдвига должна иметь тип int. Вот пример применения этих операций:

/// <summary>

/// операции сдвига

/// </summary>

public void Shift()

{

int n = 17,m =3, p,q;

p= n>>2; q = m<<2;

Console.WriteLine("n= " + n + "; m= " + m + "; p=n>>2 = "+p

+ "; q=m<<2 " + q);

long x=-75, y =-333, u,v,w;

u = x>>2; v = y<<2; w = x/4;

Console.WriteLine("x= " + x + "; y= " + y + "; u=x>>2 = "+u

+ "; v=y<<2 " + v + "; w = x/4 = " + w);

}//Shift

Логические операции

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

int k1 = 7;

if (k1) Console.WriteLine("ok!");

незаконна в программах на C#. На этапе трансляции возникнет ошибка, поскольку вычисляемое условие имеет тип int, а неявное преобразование этого типа к типу bool отсутствует.

В языке C# более строгие правила действуют и для логических операций. Так, запись

if(k1 && (x>y)),

корректная в языке C++, приводит к ошибке в программах на C#, поскольку операция && определена только для операндов типа bool, а в данном выражении один из операндов имеет тип int. В языке C# в данных ситуациях следует использовать записи:

if(k1>0)

if((k1>0) && (x>y))

После этого важного предупреждения перейду к более систематическому изложению некоторых особенностей выполнения логических операций. Так же, как и в языке C++, логические операции делятся на две категории: одни выполняются над логическими значениями операндов, другие осуществляют выполнение логической операции над битами операндов. По этой причине в C# существуют две унарные операции отрицания - логическое отрицание, заданное операцией " !", и побитовое отрицание, заданное операцией " ~ ". Первая из них определена над операндом типа bool, вторая - над операндом целочисленного типа, начиная с типа int и выше ( int, uint, long, ulong ). Результатом операции во втором случае является операнд, в котором каждый бит заменен его дополнением. Приведу пример:

/// <summary>

/// Логические выражения

/// </summary>

public void Logic()

{

//операции отрицания ~,!

bool b1,b2;

b1 = 2*2==4; b2 =!b1;

//b2= ~b1;

uint j1 =7, j2;

j2= ~j1;

//j2 = !j1;

int j4 = 7, j5;

j5 = ~j4;

Console.WriteLine("uint j2 = " + j2 +" int j5 = " + j5);

}//Logic

В этом фрагменте закомментированы операторы, приводящие к ошибкам. В первом случае была сделана попытка применения операции побитового отрицания к выражению типа bool, во втором - логическое отрицание применялось к целочисленным данным. И то, и другое в C# незаконно. Обратите внимание на разную интерпретацию побитового отрицания для беззнаковых и знаковых целочисленных типов. Для переменных j5 и j2 строка битов, задающая значение - одна и та же, но интерпретируется по-разному. Соответствующий вывод таков:

uint j2 = 4294967288 int j5 = -8

Бинарные логические операции " && - условное И " и " || - условное ИЛИ " определены только над данными типа bool. Операции называются условными или краткими, поскольку, будет ли вычисляться второй операнд, зависит от уже вычисленного значения первого операнда. В операции " && ", если первый операнд равен значению false, то второй операнд не вычисляется и результат операции равенfalse. Аналогично, в операции " || ", если первый операнд равен значению true, то второй операнд не вычисляется и результат операции равен true. Ценность условных логических операцийзаключается не в их эффективности по времени выполнения. Часто они позволяют вычислить логическое выражение, имеющее смысл, но в котором второй операнд не определен. Приведу в качестве примера классическую задачу поиска по образцу в массиве, когда разыскивается элемент с заданным значением (образец). Такой элемент в массиве может быть, а может и не быть. Вот типичное решение этой задачи в виде упрощенном, но передающем суть дела:

//Условное And - &&

int[] ar= {1,2,3};

int search = 7; int i=0;

while ((i < ar.Length) && (ar[i]!= search)) i++;

if(i<ar.Length) Console.WriteLine("Образец найден");

else Console.WriteLine("Образец не найден");

Если значение переменной search (образца) не совпадает ни с одним из значений элементов массива ar, то последняя проверка условия цикла while будет выполняться при значении i, равном ar.Length. В этом случае первый операнд получит значение false, и, хотя второй операнд при этом не определен, цикл нормально завершит свою работу. Второй операнд не определен в последней проверке, поскольку индекс элемента массива выходит за допустимые пределы (в C# индексация элементов начинается с нуля). Заметьте, что "нормальная" конъюнкция требует вычисления обеих операндов, поэтому ее применение в данной программе приводило бы к выбросу исключения в случае, когда образца нет в массиве.

Три бинарные побитовые операции - " & - AND " , " | - OR ", " ^ - XOR " используются двояко. Они определены как над целыми типами выше int, так и над булевыми типами. В первом случае они используются как побитовые операции, во втором - как обычные логические операции. Иногда необходимо, чтобы оба операнда вычислялись в любом случае, тогда без этих операций не обойтись. Вот пример первого их использования:

//Логические побитовые операции And, Or, XOR (&,|,^)

int k2 = 7, k3 = 5, k4, k5, k6;

k4 = k2 & k3; k5 = k2| k3; k6 = k2^k3;

Console.WriteLine("k4 = " + k4 + " k5 = " + k5 + " k6 = " + k6);

Приведу результаты вывода:

k4 = 5 k5 = 7 k6 =2

Приведу пример поиска по образцу с использованием логического AND:

i=0; search = ar[ar.Length - 1];

while ((i < ar.Length) & (ar[i]!= search)) i++;

if(i<ar.Length) Console.WriteLine("Образец найден");

else Console.WriteLine("Образец не найден");

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

Условное выражение

В C#, как и в C++, разрешены условные выражения. Конечно, без них можно обойтись, заменив их условным оператором. Вот простой пример их использования, поясняющий синтаксис их записи:

//Условное выражение

int a = 7, b= 9, max;

max= (a>b) ? a:b;

Console.WriteLine("a = " + a + "; b= " + b +

"; max(a,b) = " + max);

Условное выражение начинается с условия, заключенного в круглые скобки, после которого следует знак вопроса и пара выражений, разделенных двоеточием " : ". Условием является выражение типа bool. Если оно истинно, то из пары выражений выбирается первое, в противном случае результатом является значение второго выражения. В данном примере переменная max получит значение 9.

Наши рекомендации