Автор Тема: Битовые и логические операции  (Прочитано 12005 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Johnny

  • Создатель
  • Оплот сообщества
  • *
  • Сообщений: 473
    • Просмотр профиля
Битовые и логические операции
« : Март 26, 2014, 09:11:51 am »
Приведенная информация актуальна только для версии 4.10, находящейся на тестировании

В версии 4.10 была изменена логика работы условий и наравне с этим появилась возможность использовать в вычислениях наравне с привычной арифметикой битовые операции.


Перед началом я напомню, что в компьютере все – в двоичном виде, потому что это исключительно удобно в плане электроники. В математике же любое число может быть представлено в любом виде, в десятичном, в двоичном, в шестнадцатеричном. В каком бы виде число не было представлено, это по прежнему то же число. Несмотря на то, что мы с детства привыкли работать в десятеричной системе счисления, а компьютер понимает лишь нули и единицы.
Так же, говоря "истина" я имею ввиду "1",а говоря "1" я имею ввиду "истина". "0" это "ложь". Такой подход обусловлен тем, что битовые операции неотделимы от логических высказываний.
Битовые операции возможны лишь с целыми положительными числами. И нулем.
Так же я напоминаю что "and", "or" и "xor" являются синонимами операций "&","|" и "^" соответственно. При этом с точки зрения кликера, "роднее" ему именно знаковые обознаения операций и поэтому я рекомендовал бы использовать именно их (меньше шанс что парсер "споткнется" в каком либо "особом случае"). Однако поскольку это учебная статья, в примерах я буду использовать первый набор, потому что для новичков он нагляднее.

Итак приступим. Бросаемся в бой сразу с готовым скриптом. Я напоминаю что версия должна быть не ниже 4.10
Код: Clickermann
  1. $var = 15 and 6
  2. print($var)
  3.  
Выполнив этот код, вы получите в результате 6. То есть ничего не изменится. Рассмотрим как получается данный результат.
"15" это десятичное представление числа. Это же число представленное в двоичном виде будет выглядеть как 00001111 (для соблюдения стандарта будет оперировать одним байтом, т.е. восьми битами; незначащие разряды забьем нулями). Вы можете убедиться что это так, включив калькулятор в Win7 и переведя его в режим "Программист" (этот удобный калькулятор одна из причин моего окончательного перехода на семерку). "6" в двоичном виде это 00000110.
Выполняем операцию. Для удобства восприятия запишет одно число под другим.
00001111
00000110
И теперь просто вертикально (сверху вниз, по столбцам) проверяем привычное нам условие. Если вверху и внизу 1, то и в результате будет 1. В другом случае будет 0. Так работает операция AND и вы об этом уже знаете, если хоть раз писали комплексное условие.
00001111  // 15
          // and
00000110  // 6
00000110  // Результат 6
Повторим опыт с другими числами. Возьмем 51 и 60. Результатом будет 48. Смотрим как получилось.
76543210  // Биты, No
--------
00110011  // 51
00111100  // 60
00110000  // 48
Таким образом истину образует только пара битов 4 и 5 (биты считаются справа налево, первый бит имеет индекс 0), в которых в обоих числах единицы.
Стоит отметить, что правило про "перемену мест" справедливо для всех битовых операций. Вы легко можете проверить это простым примером на основе предыдущей задачи
Код: Clickermann
  1. $var = 51 and 60
  2. print($var)
  3. $var = 60 and 51
  4. print($var)
  5.  
Имея эти базовые знания быстро освоим операции OR и XOR
Если для операции AND нужно для истины чтобы оба бита были 1, то для OR хватит и одного из них. Перепишем пример с 51 и 60.
00110011  // 51
00111100  // 60
00111111  // 63
Как вы видите «единички спустились» почти во все разряды кроме последних двух (6-ого и 7-ого). Для тех кто не понял почему, я напомню что и 1 or 0 = 1 и 1 or 1 = 1. Лишь 0 or 0 = 0
И завершим нашу лекцию наиболее интересной (и по этому редко используемой) операцией XOR. Это нечто среднее между AND и OR. Для того что бы XOR вернул истину, нужно что бы ЛИШЬ ОДИН из пары был истиной. Таким образом 1 xor 1 = 0 и 0 xor 0 = 0. А вот 1 xor 0 = 1.
Снова вернемся к нашим крайне удачным числам 51 и 60.
00110011  // 51
00111100  // 60
00001111  // 15
Как вы видите "разномастными" являются первые четыре пары бит (0..3). Все остальные являются одинаковыми и несмотря на 0 или 1, для xor важно лишь различие.
У операции xor есть еще одно свойство если два раза подрояд произвести операцию xor при помощи одного и того же числа, то вы получите исходное число. Иллюстрирует это простой пример
Код: Clickermann
  1. $var = 51
  2. $key = 60
  3.  
  4. $var = $var xor $key
  5. print("xor: ", $var)
  6.  
  7. $var = $var xor $key
  8. print("xor again: ", $var)
  9.  
Поэтому XOR является самым простым (и одновременно быстрым) алгоритмом шифрования. Не знаю как вам это пригодится для написания скриптов на линейку…
Поздравляю. Вы освоили битовые операции.

Теперь, не отрываясь от чтения, рассмотрим специфику работы логических высказываний.
В версии 4.10 считается, что операции отношения  >, <, = (если речь не идет о присваивании значения) являются такими же операциями как сложение или вычитание (или битовые операции). Однако в зависимости от истинности результатом будет 0 или 1.
Рассмотрим пример.

$var = 5 > 3
При этом $var = 1, потому что 5 очевидно больше 3. Если бы было меньше, то результат был бы 0.
Более сложный случай
$var = (5 > 3) and (2 > 3)
Результат $var = 0, потому что получается (1) and (0), ведь 2 не больше 3. Ну а 1 and 0, как вы уже знаете дадут 0. Если бы это было в условии if
Код: Clickermann
  1. if ((5 > 3) and (2 > 3) )
  2.  print("ok")
  3. end_if
  4.  
То условие бы не выполнилось, потому что результат логического высказывания (состоящего из сравнений и их битового произведения – and) будет 0. Для того что бы "if выполнился" он должен быть больше нуля. Стоит заметить что не обязательно "1" а именно больше нуля.

Простые примеры для понимания
Код: Clickermann
  1. // высказывание истинно ( > 0 ), условие выполняется
  2. if(100)
  3.  print("ok")
  4. end_if
  5. // высказывание ложно ( < 0 ), условие не выполняется
  6. if(-100)
  7.  print("ok")
  8. end_if
  9. // высказывание ложно (= 0), условие не выполняется
  10. if ( 1 and 0 )
  11.  print("ok")
  12. end_if
  13. // высказывание истинно (> 0, помните же пример из битовых операций?), условие выполняется
  14. if ( 51 and 60 )
  15.  print("ok")
  16. end_if
  17. // высказывание истинно, условие выполняется, приоритетные скобки поддерживаются
  18. if ( (51 and 60) or 1 )
  19.  print("ok")
  20. end_if
  21.  
Важно отметить важность приоритетных скобок. Дело в том что и у битовых операций есть свои приоритеты: операция AND (ее еще называют битовым произведением) выполняется первой. Если порядок действий не обозначен скобками. Пример
Код: Clickermann
  1. // пример 1
  2. $var = 3 or 15 and 12
  3. print($var) // 15
  4.  
  5. // пример 2
  6. $var = (3 or 15) and 12
  7. print($var) // 12
  8.  
Разберем пример 1
3 or 15 and 12 // первым по приоритету выполняется операция and получаем
3 or 12 // так как 15 and 12 = 12
И в результате будет 15, так как 3 or 12 = 15
Разберем пример 2
(3 or 15) and 12 // первым как и везде идет операция в скобках получаем
(15) and 12 // и в результате 12

Напоследок приведем совершенно дикий для новичка пример
Код: Clickermann
  1. if( ((10 + (2 > 1)) and 8 + 2) or 3 )
  2.  print("true")
  3. else
  4.  print("nope")
  5. end_if
  6.  
Выполнится ли условие? Да, потому что результат высказывания будет 11, а это явно больше 0, чего достаточно для выполнения блока условия, соответствующего истине. Если вы сможете самостоятельно просчитать это выражение (и запомнить что условия считаются истинными когда они больше 0) то вы способный программист.

Cartman

  • Зашел в гости
  • *
  • Сообщений: 6
    • Просмотр профиля
Re: Битовые и логические операции
« Ответ #1 : Июль 06, 2014, 04:53:20 pm »
Что то я не понял на счет условия, скобки что, наоборот раскрываются?

Johnny

  • Создатель
  • Оплот сообщества
  • *
  • Сообщений: 473
    • Просмотр профиля
Re: Битовые и логические операции
« Ответ #2 : Август 19, 2014, 08:43:52 am »
Больше примеров
Я больше чем уверен, что многие не оценили (не вникли в) битовые операции, поэтому решил привести несколько примеров, показывающих сферы их применения. Возможно примеры будут дополняться.


Проверка равенства нескольких переменных в шапке одного условия
Код: Clickermann
  1. // изменение хотя бы одной из переменных ведет к "порче" всего условия
  2. $var1 = 333
  3. $var2 = 333
  4. $var3 = 333
  5. $var4 = 333
  6. $var5 = 333
  7.  
  8. if ( ($var1 & $var2 & $var3 & $var4 & $var5) = 333  )
  9.  print("true")
  10. else
  11.  print("false")
  12. end_if
  13.  
  14. halt



Простой переключатель флага с 0 на 1 и обратно
Код: Clickermann
  1. $swch = 1
  2.  
  3. // бесконечный цикл
  4. while(1)
  5.  print($swch)
  6.  $swch = $swch xor 1 // вся суть
  7.  wait(1)
  8. end_cyc
  9.  
  10. halt


Проверка четности значения
Стоит заметить что 0 данным кодом тоже будет считаться четным
Код: Clickermann
  1. // бесконечный цикл
  2. while(1)
  3.   $value = rnd(1,99) // генерация случайного числа
  4.  
  5.   if ( $value and 1 ) // проверка первого бита $value
  6.      print($value ," - нечет")
  7.   else
  8.      print($value, " - чет")
  9.   end_if
  10.  
  11.   wait(1)
  12. end_cyc
  13.  
  14. halt