Г. Шилдт - С#4.0 Полное руководство (1160795), страница 22
Текст из файла (страница 22)
Сдвиг влево « Сдвиг вправо » Ниже приведена общая форма для этих операторов; значение « число битов значение » число битов где число битов — это число двоичных разрядов, на которое сдвигается указанное эна чение. При сдвиге влево все двоичные разряды в указываемом значении сдвигаются на одну позицию влево, а младший разряд сбрасывается в нуль. При сдвиге вправо все двоичные разряды в указываемом значении сдвигаются на одну позицию вправо. Если вправо сдвигается целое значение без знака, то старший разряд сбрасывается в нуль. А если вправо сдвигается целое значение со знаком, то разряд знака сохраняется. Напомним, что для представления отрицательных чисел старший разряд целого числа устанавливается в 1.
Так, если сдвигаемое значение является отрицательным, то при Глава 4. Операторы 115 каждом сдвиге вправо старший разряд числа устанавливается в 1. А если сдвигаемое значение является положительным, то при каждом сдвиге вправо старший разряд числа сбрасывается в нуль. При сдвиге влево и вправо крайние двоичные разряды теряются. Восстановить потерянные при сдвиге двоичные разряды нельзя, поскольку сдвиг в данном случае не является циклическим.
Ниже приведен пример программы, наглядно демонстрирующий действие сдвига влево и вправо. В данном примере сначала задается первоначальное целое значение, равное 1. Это означает, что младший разряд этого значения установлен. Затем это целое значение сдвигается восемь раз подряд влево. После каждого сдвига выводятся восемь младших двоичных разрядов данного значения. Далее процесс повторяется, но на этот раз 1 устанавливается на позиции восьмого разряда, а по существу, задается целое значение 128, которое затем сдвигается восемь раз подряд вправо.
// Продемонстрировать применение операторов сдвига. пяьпч Яуясяв," с1аяя звьГГОево ( яяясьс чотг( Наьп () ( гпс ча1 = 1," Гог(тпя г = 01 1 < 81 1++) ( Гог(1пс <=128) Г > О) Г = С/2) ( 11((ча1 я Ю != 0) Сопяо1е.нгьяе("1 ") 11((ча1 я Г) == 0) Сопяо1е.игьсе("0 ") Сопяо1е. Хгтге11пе () 1 чя1 = ча1 « 11 // сдвиг влево ) сопяо1я.нгтгеььпе() 1 ча1 = 128) Гог(ьпг 1 = 01 1 < 81 1тт) ( Гог(ьпг 1=1281 С > О( 1 = Г/2) ( 11((ча1 я Г) != 0) Сопяо1е.иг11е("1 "); 11((чя1 я С) == 0) Сопяо1е.иг1се("0 ")) ) Сопяо1я.иг1яе11пе () 1 чя1 = ча1 » 1; // сдвиг вправо ) Результат выполнения этой программы выглядит следующим образом. 000000 000000 000001 000010 000100 001000 010000 100000 0 1 1 О 0 0 0 0 0 0 0 0 0 0 0 0 116 Часть!.
Язык С(г Двоичные разряды соответствуют форме представления чисел в степени 2, и поэтому операторы сдвига могут быть использованы для умножения или деления целых значений на 2. Так, при сдвиге вправо целое значение удваивается, а при сдвиге влево — уменьшается наполовину. Разумеется, все это справедливо лишь в том случае, если крайние разряды не теряются при сдвиге в ту или иную сторону. Ниже приведен соответствующий пример.
// Применить операторы сдвига для умножения и деления на 2. цвьпд Зувоев) с1а*в Мц1вшч ввавьс чоьс Маьп() ( ьпс и) и = 10; Сопво1е.Хгьгевьпе (" Значение переменной и: " + и) // Умножить на 2. и = и «1) Соп*о1е.игьоешпе("Значение переменной и после "операции и = и * 2: " 4 и)) // Умножить на 4. и = и «2) Сопво1е.Хгьоевьпе("Значение переменной и после "операции и = и * 4: " ь и)) // Разделить на 2. п=п»1; сопво1е.хгтсеььпе("значение переменной и после "операции и = и / 2: " + и)) Разделить на 4, п=п»2) Сопво1е.Хгьвеоьпе("Значение переменной и после "операции и и / 4: " + и); Сопво1е.нгьгевьпе()г // Установить переменную и в исходное состояние.
и = 10; Сопво1е.иг1севьпе("Значение переменной и: " т и)) 1ОООО О1ООО ОО1ОО ООО(О ОООО1 ооооо ооооа ооооо ооо ооо ооо ооо оаа 1ОО О1О ОО1 йава 4. Операторы 117 Умножить на 2 тридцать раз. п = и « 30; // данные теряются Соиао1е.нггие81ие р'Значение переменной п после "сдвига на 30 позиций влево: " е и) Ниже приведен результат выполнения этой программы. переменной п: 10 переменной п после переменной п после переменной п после переменной и после Значение Зна~ение Значение Значение Значение операции п = и * 2: 20 операции и = п * 4: 80 операции п = п ! 2: 40 операции п = п / 4: 10 Значение переменной и: 10 Значение переменной п после сдвига на 30 позиций влево: -2147483648 Поразрядные составные операторы присваивания Все двоичные поразрядные операторы могут быть использованы в составных операциях присваивания. Например, в двух приведенных ниже операторах переменной х присваивается результат выполнения операции исключающее ИЛИ над первоначальным значением переменной х и числовым значением 127.
х = х " 127; х "= 127; Оператор? Оператор 7 относится к числу самых примечательных в Са. Он представляет собой условный оператор и часто используется вместо определенных видов конструкций гв-ььеи-е1зе. Оператор 7 иногда еще называют тернарным, поскольку для него требуются три операнда. Ниже приведена общая форма этого оператора. Выражение1 7 Выражение2 : Выражениез; Здесь Вьгражение1 должно относиться к типу Ьоо1, а Выражение2 и Выражениез— к одному и тому же типу.
Обратите внимание на применение двоеточия и его местоположение в операторе 7. Значение выражения '. определяется следующим образом. Сначала вычисляется Выражение1. Если оно истинно, то вычисляется Выражение2, а полученный результат определяет значение всего выражения 7 в целом. Если же Выражение1 оказывается Обратите внимание на последнюю строку приведенного выше результата. Когда целое значение 10 сдвигается влево тридцать раз подряд, информация теряется, поскольку двоичные разряды сдвигаются за пределы представления чисел для типа Впс.
В данном случае получается совершенно "непригодное" значение, которое оказывается к тому же отрицательным, поскольку в результате сдвига в старшем разряде, используемом в качестве знакового, оказывается 1, а следовательно, данное числовое значение должно интерпретироваться как отрицательное. Этот пример наглядно показывает, что применять операторы сдвига для умножения или деления на 2 следует очень аккуратно.
(Подробнее о типах данных со знаком и без знака см. в главе 3.) 118 Часть 1. Язык С№ ложным, то вычисляется ВыраягениеЗ, и его значение становится общим для всего выражения?. Рассмотрим следующий пример, в котором переменной аЬяуа1 присваивается значение переменной уа1. аЬяча1 = ча1 < 0 ? -наг : ча1? ?? получить абсолютное значение переменной ча1 В данном примере переменной аЬяча1 присваивается значение переменной ча1, если оно больше или равно нулю.
Если же значение переменной ча1 отрицательно, то переменной аЬяча1 присваивается результат отрицания этого значения, что в итоге дает положительное значение. Ниже приведен еще один пример применения оператора?. В данной программе одно число дели~ся на другое, но при этом исключается деление на нуль. ?/ Исключить деление на нуль, используя оператор?. ияьпд Зуяпеюг с1аяя Нозетопьч ( ясасьс того Маял() ( гпг теяп1С( гоп(ьпс 1 = -5? т < бг т++) теяо1С = 1 != 0 ? 100 / 1 : Ог 11(1 != 0) Сопяо1е.Хт1геЬгпе("100 / " + 1 + " равно " + теяс1С)Г Выполнение этой программы дает следующий результат.
100 / -5 равно -20 100 / -4 равно -25 100 / -3 равно -33 100 / -2 равно -50 100 / -1 равно -100 100 / 1 равно 100 100 / 2 равно 50 100 / 3 равно 33 100 / 4 равно 25 100 / 5 равно 20 Обратите особое внимание на следующую строку из приведенной вьппе программы. теяо1С = г != 0? 100 / 1: Ог В этой строке переменной геяп10 присваивается результат деления числа 100 на значение переменной 1. Но это деление осуществляется лишь в том случае, если значение переменной 1 не равно нулю.
Когда же оно равно нулю, переменной геяп1С присваивается значение, обнуляющее результат. Присваивать переменной результат выполнения оператора '. совсем не обязательно. Например, значение, которое дает оператор?, можно использовать в качестве аргумента при вызове метода. А если все выражения в операторе? относятся к типу Ьоо1, то такой оператор может заменить собой условное выражение в цикле или операторе Глава 4. Операторы 119 гу. В приведенном ниже примере программы выводятся результаты деления числа 100 только на четные, ненулевые значения.
Разделить только на четные, ненулевые значения. ояьпэ Яуятезг с1аяя Нозего01ч2 ( ятатгс уота На1п() ( Гог (ьпт 1 = -51 1 < ГП 1++) ьт(1 )= 0 7 (142 == О): ьа1яе) Сопяо1е.ит1ге11пе("100 / " + 1 а " равно " + 100 / 1) Обратите внимание на оператор 11 в приведенной выше программе. Если значение переменной 1 равно нулю, то оператор 1Г дает ложный результат. А если значение переменной 1 не равно нулю, то оператор 11 дает испгнный результат, когда значение переменной 1 оказывается четным, и ложный результат, если оно нечетное. Благодаря этому допускается деление только на четные и ненулевые значения. Несмотря на то что данный пример служит лишь для целей демонстрации, подобные конструкции иногда оказываются весьма полезными.
Использование пробелов и круглых скобок В выражении на С№ допускается наличие символов табуляции и пробелов, благодаря которым оно становится более удобным для чтения. Например, оба приведенных ниже выражения, по существу, одинаковы, но второе читается легче. к=10/у*(127+к); х = 10 / у * (127 т х)," Скобки могут служить для группирования подвыражений, по существу, повышая' порядок предшествования заключенных в них операций, как в алгебре. Применение лишних или дополнительных скобок не приводит к ошибкам и не замедляет вычис ление выражения.