什么是按位运算符?


129

我是一个仅出于乐趣而编写代码的人,并且在学术或专业环境中都没有真正地去研究它,所以像这些按位运算符之类的东西真的使我无所适从。

我正在阅读一篇有关JavaScript的文章,该文章显然支持按位操作。我一直看到该操作在某些地方提到过,并且我尝试阅读以弄清楚它到底是什么,但是我似乎一点都没明白。那是什么 明确的例子会很棒!:D

再问几个问题-按位运算的一些实际应用是什么?您什么时候可以使用它们?


2
对于其他问题,您可能想添加一个新的SO问题并参考该问题。这样,您可能会得到更好的答案。
格雷格(Greg Hewgill)

Answers:


186

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

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

 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)对当前值进行XOR,在这种情况下,它将关闭LEFT然后打开RIGHT。

移位在某些情况下很有用。

x << y

是相同的

x * 2 y

如果您需要快速乘以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)

x << n,因此n必须为2 ^ value的形式?
艾哈迈德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

每列中的每一对位都通过“ AND”功能运行,以在底行给出相应的输出位。因此,上述表达式的答案是4。CPU(在此示例中)并行完成了8个单独的“ AND”操作,每列一个。

我之所以这样说是因为我仍然记得有这个“ AHA!”。我多年前了解这一点的时刻。


哇,这现在变得更有意义了。听起来比看起来复杂得多。谢谢。我不确定哪一个是正确的答案,因为有很多好的答案,我不确定。.谢谢
单击

27

按位运算符是一次只能进行一点运算的运算符。

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

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

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

仅当其输入为0时,NOT才为1。

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

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;否则,结果为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。最左边的符号位被丢弃。


“如果这些位是互补的”-是吗?
安德烈·秋金

@AndreyTyukin两个位是互补的,如果它们中的一个是1且另一个是0。
杰夫希尔曼

@JeffHillman根据您在注释中的描述,1和1不是“互补的”。然后我不清楚为什么要给与不1 | 1给,以及为什么应该与有所不同。几天前,我不得不将此Q / A作为重复目标,并且我希望10年后,对于此类问题,可以有一个更清晰的规范重复。10|^
安德烈·秋金

4

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

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

会得出(以二进制形式):
x = 1000
y = 0001

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

或... 9十进制

希望这可以帮助。


|是或运算?
Si8

由于某种原因,这对我来说最有意义。不过仍然不确定该 x | y = 1000 0001 |部分
samayo

4

当提到术语“按位”时,有时说明它不是“逻辑”运算符。

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

以expr1 && expr2为例。

如果可以将其转换为false,则返回expr1;否则返回false。否则,返回expr2。因此,当与布尔值一起使用时,&&如果两个操作数都为true,则返回true;否则,为false。否则,返回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>

3

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

操作

  • 按位与

  • 按位或

  • 按位非

  • 按位异或

  • 等等

项目清单

    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

均为1:00000001 0为假,1为真

因此5和3的AND是1。OR(|)运算符执行相同的操作,不同的是只有一个数字必须为1才能输出1,而不要同时输出两个数字。


-5

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

因此,我的代码中有一种情况将更快,更容易阅读。我会继续睁大眼睛。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.