134

我是一个写代码只是为了好玩的人,在学术或专业环境中都没有真正深入研究过,所以像这些按位运算符这样的东西真的让我无法理解。

我正在阅读一篇关于 JavaScript 的文章,它显然支持按位运算。我一直在某些地方看到此操作,并且我尝试阅读以弄清楚它到底是什么,但我似乎根本不明白。那么它们是什么?清晰的例子会很棒!:D

还有几个问题——按位运算有哪些实际应用?你什么时候可以使用它们?

4

9 回答 9

187

由于没有人提出这些为什么有用的主题:

在处理标志时,我经常使用按位运算。例如,如果您想将一系列标志传递给操作(例如,File.Open()同时启用读取模式和写入模式),您可以将它们作为单个值传递。这是通过在位集(字节、短、整数或长)中为每个可能的标志分配它自己的位来实现的。例如:

 Read: 00000001
Write: 00000010

所以如果你想通过读写,你会通过 (READ | WRITE) 然后将两者组合成

00000011

然后可以在另一端解密,例如:

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

检查

00000011 &
00000001

返回

00000001

这不是 0,因此该标志确实指定了 READ。

您可以使用 XOR 来切换各种位。我在使用标志指定方向输入(上、下、左、右)时使用了它。例如,如果一个精灵水平移动,我希望它转身:

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

在这种情况下,我只需将当前值与 (LEFT | RIGHT) 进行异或,这将关闭 LEFT 并打开 RIGHT。

移位在几种情况下很有用。

x << y

是相同的

x * 2

如果您需要快速乘以 2 的幂,但要注意将 1 位移到最高位 - 这会使数字变为负数,除非它是无符号的。在处理不同大小的数据时它也很有用。例如,从四个字节中读取一个整数:

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

假设 A 是最重要的字节,而 D 是最少的。它最终会是:

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

颜色通常以这种方式存储(最高有效字节被忽略或用作 Alpha):

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)
于 2008-11-10T00:39:20.750 回答
29

值得注意的是,作为其他答案列出的单位真值表一次只能处理一个或两个输入位。使用整数时会发生什么,例如:

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。CPU 已经(在这个例子中)并行完成了 8 次单独的“AND”操作,每列一个。

我提到这个是因为我还记得有这个“啊哈!” 多年前我得知这一点的那一刻。

于 2008-11-10T00:11:05.223 回答
28

位运算符是一次处理一个位的运算符。

仅当两个输入都为 1 时 AND 才为 1。

如果一个或多个输入为 1,则 OR 为 1。

仅当其输入之一恰好为 1 时,XOR 才为 1。

只有当它的输入为 0 时才为 1。

这些可以最好地描述为真值表。输入可能性位于顶部和左侧,结果位是显示在两个输入交叉处的四个(在 NOT 的情况下为两个,因为它只有一个输入)值之一。

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
于 2008-11-10T00:04:28.373 回答
17

这些是位运算符,JavaScript 都支持:

  • op1 & op2--AND运算符比较两个位,如果两个位都为 1,则生成结果 1;否则,它返回 0。

  • op1 | op2--OR运算符比较两个位,如果位互补,则生成结果 1;否则,它返回 0。

  • op1 ^ op2--EXCLUSIVE-OR运算符比较两个位,如果其中一个位为 1,则返回 1,如果两个位为 0 或 1,则返回 0。

  • ~op1--COMPLEMENT运算符用于反转操作数的所有位。

  • op1 << op2--SHIFT LEFT运算符向左移动位,丢弃最左边的位,并将最右边的位赋值为 0。每次向左移动都会有效地将 op1 乘以 2。

  • op1 >> op2--SHIFT RIGHT运算符向右移动位,丢弃最右边的位,并将最左边的位赋值为 0。每次向右移动有效地将 op1 分成两半。最左边的符号位被保留。

  • op1 >>> op2-- SHIFT RIGHT-ZERO FILL运算符将位向右移动,丢弃最右边的位,并将最左边的位赋值为 0。每次向右移动有效地将 op1 分成两半。最左边的符号位被丢弃。

于 2008-11-10T00:03:13.273 回答
4

为了进一步分解,它与所讨论值的二进制表示有很大关系。

例如(十进制):
x = 8
y = 1

会出来(二进制):
x = 1000
y = 0001

从那里,您可以进行计算操作,例如“与”或“或”;在这种情况下:
x | y =
1000
0001 |
------
1001

或...9 十进制

希望这可以帮助。

于 2008-11-10T00:14:43.203 回答
4

当提到“按位”一词时,有时会澄清这不是“逻辑”运算符。

例如,在 JavaScript 中,按位运算符将其操作数视为 32 位(零和一)的序列;同时,逻辑运算符通常与布尔(逻辑)值一起使用,但可以与非布尔类型一起使用。

以 expr1 && expr2 为例。

如果可以转换为 false,则返回 expr1;否则,返回 expr2。因此,当与布尔值一起使用时,如果两个操作数都为真,则 && 返回真;否则,返回 false。

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>
于 2008-11-10T00:26:02.040 回答
4

在数字计算机编程中,按位运算在一个或多个位模式或二进制数字的各个位级别上进行操作。它是处理器直接支持的快速、原始的操作,用于操作值以进行比较和计算。

操作

  • 按位与

  • 按位或

  • 按位非

  • 按位异或

  • ETC

项目清单

    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 ;
}
  • 异或门加密是一种流行的技术,因为它的复杂性和程序员可以使用。
  • 从技术面试的角度来看,按位异或运算符是最有用的运算符。

按位移位仅适用于 +ve 数字

位逻辑的使用范围也很广

于 2016-04-21T07:02:19.427 回答
1

以这种方式思考它可能会有所帮助。这就是 AND (&) 的工作原理:

它基本上说这两个数字都是数字,所以如果你有两个数字 5 和 3,它们将被转换为二进制,计算机会认为

         5: 00000101
         3: 00000011

都是一:00000001 0 为假,1 为真

所以 5 和 3 的 AND 是一。OR (|) 运算符执行相同的操作,只是其中一个数字必须为 1 才能输出 1,而不是两者。

于 2014-06-20T14:30:49.533 回答
-5

我一直听说 JavaScript 位运算符有多慢。我为我最新的博客文章做了一些测试,发现它们在几个测试中比算术替代方法快 40% 到 80%。也许他们曾经很慢。在现代浏览器中,我喜欢它们。

我的代码中有一个案例,因此会更快、更容易阅读。我会睁大眼睛了解更多。

于 2009-02-10T00:35:44.707 回答