Урок Логические и побитовые операторы

Для нормальной работы платформы воспользуйтесь персональным компьютером.

Видеокурсы по
программированию

  • Главная >
  • Каталог практикумов >
  • Практикум «Java Starter» >
  • org/ListItem»> Урок «Логические и побитовые операторы»

Логические и побитовые операторы

Ошибка Ошибка

Произошла техническая ошибка! Мы приносим извинения за причиненные неудобства. Перейдите, пожалуйста, к выполнению следующего задания.

Урок завершен

Правильных ответов: {{response.correctAnswers}}

Неправильных ответов: {{response.wrongAnswers}}

Баллов за урок: {{response.lessonScores}}

Всего баллов: {{response.totalScores}}

Завершить

Подсказка{{currentUserTask. currentHint + 1}}/{{currentTask.hintsCount}}

{{hint}}

Регистрация через

или E-mail

Нажав на кнопку «Зарегистрироваться»,
Вы соглашаетесь с условиями использования.

Уже есть аккаунт

Получите курс бесплатно

Вы выбрали курс для изучения
«»
Чтобы получить доступ к курсу, зарегистрируйтесь на сайте.

РЕГИСТРАЦИЯ

Спасибо за регистрацию

Перейдите на почту и подтвердите Ваш аккаунт,

чтобы получить доступ ко всем
бесплатным урокам и вебинарам на сайте ITVDN. com

ПОДТВЕРДИТЬ ПОЧТУ НАЧАТЬ ОБУЧЕНИЕ

Спасибо за регистрацию

Ваш аккаунт успешно подтвержден.
Начать обучение вы можете через Личный кабинет
пользователя или непосредственно на странице курса.

НАЧАТЬ ОБУЧЕНИЕ

Подтверждение аккаунта

На Ваш номер телефона было отправлено смс с кодом активации аккаунта. Пожалуйста, введите код в поле ввода.

Отправить код еще раз

Изменить номер телефона

Ошибка

НОУ ИНТУИТ | Лекция | Особенности представления чисел в ЭВМ

< Дополнительный материал  || Лекция 4: 123

Аннотация: Представление информации в компьютере. Целые числа. Вещественные числа. Арифметические и побитовые операторы языка Java. Числа произвольной длины и точности.

Ключевые слова: машинный аналог, Java, константы, множества, информация, двоичное представление, оперативная память, внешняя память, бит, количество информации, байт, килобайт, kbyte, мегабайт, гигабайт, gbyte, tbyte, ASCII, information, interchange, KOI8-R, представление, двоичный дополнительный код, система счисления, позиционная система счисления, значение, двоичная система счисления, восьмеричная система счисления, , единица, знаковый бит, Дополнение, пересечение, длина, прямой, полнота вещественных чисел, число с плавающей точкой, точность, диапазон, мантиса, нормализованное число, экспонента, расстояние, nan, класс, абсолютная величина числа, коэффициенты, вызов метода, выражение, сложение, вычитание, умножение, деление, остаток, инкремент, декремент, операции, операнд, битовые операции, аргумент, целое число, длинная арифметика

intuit.ru/2010/edi»>Как уже отмечалось ранее, множествам целых и действительных чисел в большинстве языков программирования соответствуют их машинные аналоги. В случае языка Java используемые в программах переменные величины и константы типов int и double принимают значения из множеств и соответственно. В этом параграфе мы разберемся с тем, как именно устроены эти множества, и каковы последствия того, что программы оперируют не с настоящими числами, а с элементами указанных множеств. Однако сначала — некоторые напоминания об информации вообще и ее представлении в ЭВМ.

Представление информации в компьютере

Любая информация (числовая, текстовая, звуковая, графическая и т.д.) в компьютере представляется (кодируется) в так называемой двоичной форме. Как оперативная, так и внешняя память, где и хранится вся информация, могут рассматриваться, как достаточно длинные последовательности из нулей и единиц. Под внешней памятью подразумеваются такие носители информации, как магнитные и оптические диски, ленты и т.

п.

Единицей измерения информации является бит (BInary digiT) — именно такое количество информации содержится в ответе на вопрос: нуль или один? Более крупными единицами измерения информации являются байт, килобайт (Kbyte), мегабайт (Mbyte), гигабайт (Gbyte) и терабайт (Tbyte). Один байт (byte) состоит из восьми бит, а каждая последующая величина больше предыдущей в 1024 раза.

Байта достаточно для хранения 256 различных значений, что позволяет размещать в нем любой из алфавитно-цифровых символов, если только мы можем ограничиться языками с небольшими алфавитами типа русского или английского. Первые 128 символов (занимающие семь младших бит) стандартизированы с помощью кодировки ASCII (American Standart Code for Information Interchange). Хуже обстоит дело с кодировками русского текста (символы русского алфавита расположены во второй половине таблицы из 256 символов) — их несколько, а наиболее распространенные из них сейчас две — Windows-1251 и KOI8-R.

Для кодирования всех возможных символов, используемых народами мира, одного байта мало — необходимо использовать два последовательных (стандарт Unicode). Именно так и поступают при хранении символьных ( char ) значений в языке Java.

Полезно знать, что . Учитывая, что в книге среднего размера около 300000 букв, легко подсчитать, что, даже не используя никаких средств сжатия информации, на жестком диске современного персонального компьютера емкостью в 20 гигабайт можно разместить большую библиотеку из почти 70000 книг.

Целые числа

К целочисленным типам в языке Java относятся byte, short, int и long. Для хранения значений этих типов на любом компьютере отводится один, два, четыре и восемь байт соответственно. При этом применяется представление чисел в так называемом двоичном дополнительном коде.

Напомним, что используемая нами обычная система счисления является позиционной с основанием 10. Это значит, что в ней все натуральные числа представляются с помощью десяти цифр (от нуля до девяти включительно), а значение каждой из цифр числа зависит от позиции: самая правая цифра означает число единиц ( ), вторая — десятков ( ), третья — сотен ( ) и так далее.

В -ичной системе счисления все точно также, только число 10 в предыдущем абзаце нужно всюду заменить на . Наряду с двоичной системой, в которой только две цифры (0 и 1), в информатике часто применяются восьмеричная с цифрами от нуля до 7 и шестнадцатеричная. В последнем случае в качестве цифр от десяти до пятнадцати используются буквы от до соответственно.

При записи положительных целых чисел в системе счисления с основанием (на компьютере ) все их множество оказывается состоящим из элементов вида

где величины для всех из диапазона от до нуля — это цифры -значного числа в -ичной системе счисления.

intuit.ru/2010/edi»>Перейдем теперь к вопросу представления отрицательных чисел. Для определенности рассмотрим тип byte, в котором любое число занимает ровно восемь бит. Из записи в двоичной системе счисления равенства легко найти, какой вид должно иметь неизвестное нам пока двоичное представление xxxxxxxx числа :

xxxxxxxx + 00000001 = 00000000

Ясно, что на месте символов xxxxxxxx должно быть расположено число 11111111. Правильным результатом при этом, конечно, следовало бы считать 100000000, а не 00000000, но ведь мы имеем дело с типом byte и, так как результат обязан разместиться в байте, единица «исчезает».

Итак, число должно кодироваться как 11111111. Дальнейшее уже совсем просто: для получения нужно уменьшить на единицу, что даст 11111110 ; число представляется как 11111101 и т.д.

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

Легко видеть, что при этом самым маленьким отрицательным числом, которое принадлежит типу byte, является число (двоичное представление 10000000 ), а самым большим — число 127 (представление 01111111 ). Все представимые числа (а их 256) в данном случае могут быть получены как пересечение двух множеств: множества всех целых чисел и отрезка . Интересным является следующее наблюдение: если число 01111111 увеличить на единицу, то получится 10000000, что означает следующее: !

Итак, множество элементов типа byte можно представлять себе в виде свернутого в кольцо отрезка . Принципиально ничего не меняется и для типов short, int и long — увеличивается только длина отрезка, который вырезается из действительной прямой перед сворачиванием его в кольцо. Минимальные и максимальные представимые значения для каждого из этих типов в языке Java определены, как значения констант MIN_VALUE и MAX_VALUE в классах java. lang.Short, java.lang.Integer и java.lang.Long соответственно.

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

Дальше >>

< Дополнительный материал  || Лекция 4: 123

EXP54-J. Понимание различий между побитовыми и логическими операторами — SEI CERT Стандарт кодирования Oracle для Java

Условные операторы И и ИЛИ ( && и || соответственно) ведут себя как короткое замыкание. То есть второй операнд оценивается только тогда, когда результат условного оператора не может быть выведен исключительно путем вычисления первого операнда. Следовательно, когда результат условного оператора может быть выведен исключительно из результата первого операнда, второй операнд останется невычисленным; его побочные эффекты, если таковые имеются, никогда не возникнут.

Побитовые операторы И и ИЛИ ( и и | ) не имеют короткого замыкания. Подобно большинству операторов Java, они оценивают оба операнда. Они возвращают тот же логический результат, что и && и || соответственно, но могут иметь разные общие эффекты в зависимости от наличия или отсутствия побочных эффектов во втором операнде.

Следовательно, при выполнении булевой логики можно использовать оператор & или && . Однако бывают случаи, когда поведение с коротким замыканием предпочтительнее, а в других случаях поведение с коротким замыканием вызывает тонкие ошибки.

Несоответствующий пример кода (неправильные

и )

Этот несоответствующий пример кода, полученный из Flanagan [Flanagan 2005], имеет две переменные с неизвестными переменными. Код должен проверить свои данные, а затем проверить, является ли array[i] допустимым индексом.

 целый массив[]; // Может быть нулевым
инт я; // Может быть недопустимый индекс для массива
если (массив != null & i >= 0 & i < array. length & array[i] >= 0) {
  // Использовать массив
} еще {
  // Обработка ошибки
}
 

Этот код может дать сбой из-за тех же ошибок, которые он пытается предотвратить. Если массив равен NULL или i не является допустимым индексом, ссылка на массив и массив [i] вызовет исключение NullPointerException или ArrayIndexOutOfBound. sException , которое будет выброшено. Исключение возникает из-за того, что оператор и не может предотвратить вычисление своего правого операнда, даже если вычисление его левого операнда доказывает, что правый операнд не имеет значения.

Совместимое решение (используйте

&& )

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

 int array[]; // Может быть нулевым
инт я; // Может быть недопустимый индекс для массива
если (массив != ноль && я >= 0 &&
   я < массив. длина && массив [я] >= 0) {
  // Обработка массива
} еще {
  // Обработка ошибки
}
 

Это совместимое решение использует несколько операторов if для достижения надлежащего эффекта.

 целый массив[]; // Может быть нулевым
инт я; // Может быть допустимым индексом для массива
если (массив != ноль) {
  если (я >= 0 && я <массив.длина) {
    если (массив [i] >= 0) {
      // Использовать массив
    } еще {
      // Обработка ошибки
    }
  } еще {
    // Обработка ошибки
  }
} еще {
  // Обработка ошибки
}
 

Хотя это решение правильное, оно более подробное, и его может быть сложнее поддерживать. Тем не менее, это решение предпочтительнее, когда код обработки ошибок для каждого потенциального условия отказа отличается.

Пример несовместимого кода (неправильный

&& )

Этот пример несовместимого кода демонстрирует код, который сравнивает два массива для диапазонов совпадающих членов. Здесь i1 и i2 являются допустимыми индексами массива в array1 и array2 соответственно. Переменные end1 и end2 — это индексы концов совпадающих диапазонов в двух массивах.

 если (end1 >= 0 и i2 >= 0) {
  интервал начало1 = i1;
  интервал начало2 = i2;
  в то время как (++i1 < array1.length &&
         ++i2 < массив2.длина &&
         массив1[i1] == массив2[i2]) {
    // Пока массивы совпадают
  }
  интервал конец1 = i1;
  интервал конец2 = i2;
  утверждать конец1 - начало1 == конец2 - начало2;
}
 

Проблема с этим кодом заключается в том, что когда первое условие в цикле while не выполняется, второе условие не выполняется. То есть, когда i1 достигает array1.length , цикл завершается после увеличения i1 . Следовательно, видимый диапазон для array1 больше, чем видимый диапазон для array2 , что приводит к ошибке окончательного утверждения.

Совместимое решение (используйте

и )

Это совместимое решение смягчает проблему, разумно используя и , что гарантирует, что и i1 , и i2 увеличиваются независимо от результата первого условия:

 public void exampleFunction() {
  while (++i1 < array1.length & // Не &&
         ++i2 < массив2.длина &&
         массив1[i1] == массив2[i2]){
//сделай что-нибудь
  }
} 

Применимость

Непонимание поведения побитовых и условных операторов может привести к непреднамеренному поведению программы.

Библиография

901 28

[Flanagan 2005]

§2.5.6., «Булевы операторы»

[JLS 2013]

§15.23, «Оператор условного И &&»
§15.24, «Оператор условного ИЛИ ||»

 


Побитовые операции над «байтовыми» значениями , байты, побитовые операции и операции сдвига

∟Побитовые операции над «байтовыми» значениями

В этом разделе описываются 4 типа побитовых операций: «И», «ИЛИ», «Исключающее ИЛИ» и «Дополнение», которые косвенно применяются к «байтовым» значениям через значения «int».

Что такое побитовая операция? Побитовая операция — это операция, которая требует, чтобы операнды были представлены в двоичном формате и применяет операцию по одному биту за раз.

Интересно, что Java определяет побитовые операции со значениями типа данных "int", а не со значениями типа "byte". Таким образом, побитовая операция требует, чтобы задействованные значения «int» были представлены в 32-битном двоичном формате. И операция будет применяться по 1 биту за раз, повторяясь 32 раза.

Java определяет 4 побитовые операции, называемые: «И», «ИЛИ», «Исключающее ИЛИ» и «Дополнение».

1. Побитовая операция "И" - "&": Побитовая операция "И" между двумя значениями "int" может быть описана как:

  • Представление двух операндов, двух значений "int" в две входные двоичные строки длиной 32 бита.
  • Объединение этих двух входных двоичных строк в одну выходную двоичную строку длиной 32 бита, так что значение любого бита в выходной двоичной строке равно 1 тогда и только тогда, когда оба соответствующих бита во входной двоичной строке равны 1.
  • Преобразование выходной двоичной строки в значение "int" в качестве результата операции.

На следующей диаграмме показан пример операции «&» в 3 форматах:

  Десятичный шестнадцатеричный двоичный
   858993459 33333333 00110011 00110011 00110011 00110011
и 1431655765 и 55555555 и 01010101 01010101 01010101 01010101
------------ ---------- -------------------------------------
= 286331153 = 11111111 = 00010001 00010001 00010001 00010001
 

2. Побитовая операция "ИЛИ" - "|": Побитовая операция "ИЛИ" между двумя значениями "int" может быть описана как:

  • Представление двух операндов, двух значений "int" в две входные двоичные строки длиной 32 бита.
  • Объединение этих двух входных двоичных строк в одну выходную двоичную строку длиной 32 бита, так что значение любого бита в выходной двоичной строке равно 0 тогда и только тогда, когда оба соответствующих бита во входной двоичной строке равны 0.
  • Преобразование выходной двоичной строки в значение "int" в качестве результата операции. 9": побитовая операция "исключающее ИЛИ" между двумя значениями "int" может быть описана как:

    • Представление двух операндов, двух значений "int" в две входные двоичные строки длиной 32 бита.
    • Объединение этих двух входных двоичных строк в одну выходную двоичную строку длиной 32 бита, так что значение любого бита в выходной двоичной строке равно 1 тогда и только тогда, когда один из соответствующих битов во входной двоичной строке равен 1.
    • Преобразование выходной двоичной строки в значение "int" в качестве результата операции. 0101 01010101 01010101 01010101 ------------ ---------- ------------------------------------- = 1717986918 = 66666666 = 01100110 01100110 01100110 01100110

      4. Побитовая операция "Дополнение" - "~": Побитовая операция "Дополнение" над одним значением "int" может быть описана как:

      • Представление единственного операнда, одного значения "int", в одну входную двоичную строку длиной 32 бита.
      • Преобразовать входную двоичную строку в одну выходную двоичную строку длиной 32 бита так, чтобы значение любого бита в выходной двоичной строке равно 1 тогда и только тогда, когда соответствующий бит во входной двоичной строке равен 0.