Що таке бітові оператори?


130

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

Я читав статтю про JavaScript, яка, очевидно, підтримує побітові операції. Я продовжую бачити цю операцію, згадану місцями, і я намагався читати, щоб зрозуміти, що це саме, але я просто не можу її зрозуміти. То які вони? Чіткі приклади були б чудовими! : D

Ще кілька запитань - які практичні програми розрядних операцій? Коли ви можете їх використовувати?


2
Щоб отримати додаткові запитання, ви можете додати нове запитання SO та посилатися на це. Напевно, ви отримаєте кращий набір відповідей таким чином.
Грег Х'югілл

Відповіді:


187

Оскільки ніхто не торкався теми, чому вони корисні:

Я багато використовую побітові операції під час роботи з прапорами. Наприклад, якщо ви хочете передати серію прапорів до операції (скажімо, File.Open()у режимі читання та режимі запису включені обидва), ви можете передавати їх як єдине значення. Це досягається шляхом призначення кожному можливим прапором його власного біта в бітовому наборі (байт, короткий, int або довгий). Наприклад:

 Read: 00000001
Write: 00000010

Отже, якщо ви хочете передати читання та запис, ви передасте (ЧИТАТИ | ЗАПИСЬ), який потім поєднує в собі два

00000011

Що потім можна розшифрувати на іншому кінці, як:

if ((flag & Read) != 0) { //...

який перевіряє

00000011 &
00000001

який повертається

00000001

що не дорівнює 0, тому прапор дійсно вказує ЧИТАТИ

Ви можете використовувати XOR для перемикання різних бітів. Я використовував це під час використання прапора для введення спрямованих входів (вгору, вниз, вліво, вправо). Наприклад, якщо спрайт рухається горизонтально, і я хочу, щоб він обернувся:

     Up: 00000001
   Down: 00000010
   Left: 00000100
  Right: 00001000
Current: 00000100

Я просто XOR поточне значення з (ВЛІВО | ВПРАВО), яке буде вимикати ВЛЕВО та ВПРАВО, в цьому випадку.

Зміна бітів корисна в декількох випадках.

x << y

те саме, що

х * 2 у

якщо вам потрібно швидко помножити на потужність дві, але стежте за переміщенням 1 біта у верхній біт - це робить число від’ємним, якщо воно не підписане. Це також корисно при роботі з різними розмірами даних. Наприклад, зчитування цілого числа з чотирьох байтів:

int val = (A << 24) | (B << 16) | (C << 8) | D;

Якщо припустити, що А - найзначніший байт, а D - найменший. Це закінчиться так:

A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011

Кольори часто зберігаються таким чином (найзначніший байт або ігнорується, або використовується як Альфа):

A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000

Щоб знову знайти значення, просто змістіть біти праворуч, поки вони не знаходяться внизу, а потім замаскуйте решту бітів вищого порядку:

Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF

0xFFте саме, що 11111111. Тож по суті, для Red ви б це робили:

Color >> 16 = (filled in 00000000 00000000)11111111 00010101  (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)

x << n, значить, n має бути у вигляді значення 2 ^?
Ахмед C

28

Варто зазначити, що однобітні таблиці правди, перелічені як інші відповіді, працюють лише на одному або двох вхідних бітах одночасно. Що відбувається при використанні цілих чисел, таких як:

int x = 5 & 6;

Відповідь полягає у двійковому розширенні кожного входу:

  5 = 0 0 0 0 0 1 0 1
& 6 = 0 0 0 0 0 1 1 0
---------------------
      0 0 0 0 0 1 0 0

Кожна пара бітів у кожному стовпчику виконується через функцію "І", щоб дати відповідний вихідний біт у нижньому рядку. Отже, відповідь на вищевикладений вираз - 4. ЦП виконав (у цьому прикладі) 8 окремих операцій "І" паралельно, по одному для кожного стовпця.

Я згадую про це, тому що я все ще пам’ятаю, що це було "АГА!" момент, коли я дізнався про це багато років тому.


Нічого собі, це має набагато більше сенсу зараз. Це звучало набагато складніше, ніж, мабуть, є. Дякую. Я не впевнений, яку вибрати як правильну відповідь, оскільки є багато хороших, і я не можу підняти це .. дякую
натисніть

27

Побітові оператори - це оператори, які працюють над бітом одночасно.

І є 1, лише якщо обидва його входи дорівнюють 1.

АБО 1, якщо один або декілька його входів 1.

XOR дорівнює 1, якщо точно один з його входів дорівнює 1.

НЕ є 1, лише якщо його вхід дорівнює 0.

Їх найкраще описати як таблиці істинності. Можливості введення знаходяться вгорі та зліва, отриманий біт - це одне з чотирьох (два у випадку НЕ, оскільки у нього є лише один вхід), що знаходяться на перетині двох входів.

AND|0 1      OR|0 1
---+----    ---+----
  0|0 0       0|0 1
  1|0 1       1|1 1

XOR|0 1     NOT|0 1
---+----    ---+---
  0|0 1        |1 0
  1|1 0

Одним із прикладів є те, що якщо ви хочете лише 4 нижчих біта цілого числа, ви ТАК це з 15 (двійковий 1111), так:

    203: 1100 1011
AND  15: 0000 1111
------------------
 IS  11: 0000 1011

16

Це бітові оператори, всі підтримуються в JavaScript:

  • op1 & op2- ANDОператор порівнює два біти і генерує результат 1, якщо обидва біта дорівнюють 1; в іншому випадку він повертає 0.

  • op1 | op2- ORОператор порівнює два біти і генерує результат 1, якщо біти є взаємодоповнюючими; в іншому випадку він повертає 0.

  • op1 ^ op2- EXCLUSIVE-ORОператор порівнює два біти і повертає 1, якщо будь-який біт дорівнює 1, і він дає 0, якщо обидва біта дорівнюють 0 або 1.

  • ~op1- COMPLEMENTОператор використовується для перетворення всіх бітів операнда.

  • op1 << op2- SHIFT LEFTОператор переміщує біти ліворуч, відкидає крайній лівий біт і присвоює крайнє правому біту значення 0. Кожен хід вліво ефективно множить op1 на 2.

  • op1 >> op2- SHIFT RIGHTОператор переміщає біти праворуч, відкидає крайній правий біт і присвоює крайній лівий біт значення 0. Кожен хід праворуч ефективно ділить op1 навпіл. Найбільш лівий шматочок збережений.

  • op1 >>> op2- The SHIFT RIGHT- ZERO FILLоператор переміщує біти вправо, відкидає далеко правий біт, і призначає крайній лівий біт значення 0. Кожен крок направо ефективно ділить ФП1 навпіл. Білий лівий знак біда відкидається.


"якщо біти є взаємодоповнюючими" - що?
Андрій Тюкін

@AndreyTyukin два біти є додатковими, якщо один з них 1, а другий - 0.
Джефф Хіллман

@JeffHillman Згідно з вашим описом у коментарі, 1 і 1 не є "взаємодоповнюючими". Тоді мені незрозуміло, чому 1 | 1дає 1і ні 0, і |чим тоді передбачається відрізнятися від ^. Мені довелося використовувати цю запитання як дублюючу ціль кілька днів тому, і я хотів, щоб через 10 років у когось з'явився більш чіткий канонічний дублікат для подібних питань.
Андрій Тюкін

4

Щоб розбити його трохи більше, це має багато спільного з бінарним поданням значення.

Наприклад (у десятковій кількості):
х = 8
у = 1

вийде (у двійковій формі):
х = 1000
у = 0001

Звідти ви можете робити обчислювальні операції, такі як 'і' або 'або'; в цьому випадку:
х | у =
1000 
0001 |
------
1001

або ... 9 у десятковій частині

Сподіваюся, це допомагає.


|чи АБО операції?
Si8

Чомусь це мало для мене сенс. Досі не впевнений у x | y = 1000 0001 |частині, хоча
Самайо

4

Коли згадується термін "побітові", іноді з'ясовується, що це не "логічний" оператор.

Наприклад, в JavaScript, побітові оператори трактують свої операнди як послідовність із 32 біт (нулі та одиниці) ; тим часом логічні оператори зазвичай використовуються з булевими (логічними) значеннями, але можуть працювати з не булевими типами.

Візьмемо для прикладу expr1 && expr2.

Повертає expr1, якщо його можна перетворити на false; в іншому випадку повертає expr2. Таким чином, при використанні з булевими значеннями && повертає істину, якщо обидва операнди є істинними; в іншому випадку повертається помилковим.

a = "Cat" && "Dog"     // t && t returns Dog
a = 2 && 4     // t && t returns 4

Як зазначали інші, 2 і 4 є побітним І, тому він поверне 0.

Ви можете скопіювати наступне на test.html або щось тестування:

<html>
<body>
<script>
    alert("\"Cat\" && \"Dog\" = " + ("Cat" && "Dog") + "\n"
        + "2 && 4 = " + (2 && 4) + "\n"
        + "2 & 4 = " + (2 & 4));
</script>

3

У цифровому комп'ютерному програмуванні побітова операція працює на одній або більше бітових шаблонах або двійкових цифрах на рівні їхніх окремих біт. Це швидка, примітивна дія, що безпосередньо підтримується процесором, і використовується для маніпулювання значеннями для порівнянь та обчислень.

операції :

  • розрядне І

  • побіжно АБО

  • побіжно НЕ

  • розрядний XOR

  • тощо

Елемент списку

    AND|0 1        OR|0 1 
    ---+----      ---+---- 
      0|0 0         0|0 1 
      1|0 1         1|1 1 

   XOR|0 1        NOT|0 1 
   ---+----       ---+--- 
     0|0 1           |1 0 
     1|1 0

Напр.

    203: 1100 1011
AND  15: 0000 1111
------------------
  =  11: 0000 1011

Використання побітового оператора

  • Оператори зсуву вліво і вправо зсуву еквівалентні множенню та діленню на x * 2 y відповідно.

Напр.

int main()
{
     int x = 19;
     printf ("x << 1 = %d\n" , x <<1);
     printf ("x >> 1 = %d\n", x >>1);
     return 0;
}
// Output: 38 9
  • Оператор & можна використовувати для швидкої перевірки, чи число непарне або парне

Напр.

int main()
{
    int x = 19;
    (x & 1)? printf("Odd"): printf("Even");
    return 0;
 }
// Output: Odd
  • Швидкий пошук мінімуму x та y без if elseзаяви

Напр.

int min(int x, int y)
{
    return y ^ ((x ^ y) & - (x < y))
}
  • Десяткове значення для бінарного перетворення

Напр.

#include <stdio.h>
int main ()
{
    int n , c , k ;
    printf("Enter an integer in decimal number system\n " ) ;
    scanf( "%d" , & n );
    printf("%d in binary number
    system is: \n " , n ) ;
    for ( c = 31; c >= 0 ; c -- )
    {
         k = n >> c ;
         if ( k & 1 )
              printf("1" ) ;
         else
              printf("0" ) ;
      }
      printf(" \n " );
      return 0 ;
}
  • Шифрування воріт XOR - популярна техніка, завдяки своїй сумісності та практичному використанню програмістом.
  • бітовий оператор XOR є найбільш корисним оператором з точки зору технічного інтерв'ю.

побітове перемикання працює лише з номером + ve

Також існує широкий спектр використання побітової логіки


"сумісність і знову ..."?
Джонатан Крос

The left-shift and right-shift operators are equivalent to multiplication and division by x * 2y respectively.Це вірно! muyiy.cn/question/program/102.html
xgqfrms

моє рішення repl.it/@xgqfrms/…
xgqfrms

1

Це може допомогти подумати про це так. Ось як працює AND (&):

В основному це означає, що обидва ці числа одиниці, тому якщо у вас є два числа 5 і 3, вони будуть перетворені в двійкові, і комп'ютер подумає

         5: 00000101
         3: 00000011

обидва є одним: 00000001 0 неправдиво, 1 правда

Отже, І 5 і 3 - це одне ціле. Оператор OR (|) робить те саме, за винятком лише одного з номерів, який повинен бути одним, щоб вивести 1, а не обидва.


-5

Я постійно слухав про те, наскільки повільними були бітові оператори JavaScript. Я зробив кілька тестів для моєї останньої публікації в блозі і виявив, що вони на 40% до 80% швидше, ніж арифметична альтернатива в декількох тестах. Можливо, вони були повільними. У сучасних браузерах я їх люблю.

У моєму коді є один випадок, який через це буде швидше і легше читати. Я буду тримати очі відкритими для більше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.