博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bitwise operation and usage
阅读量:4030 次
发布时间:2019-05-24

本文共 11320 字,大约阅读时间需要 37 分钟。

Consider this code:

x = 1        # 0001x << 2       # Shift left 2 bits: 0100# Result: 4x | 2        # Bitwise OR: 0011# Result: 3x & 1        # Bitwise AND: 0001# Result: 1

I can understand the arithmetic operators in Python (and other languages), but I never understood 'bitwise' operators quite well. In the above example (from a Python book), I understand the left-shift but not the other two.

Also, what are bitwise operators actually used for? I'd appreciate some examples.

 
8  
This may be of interest:  –   

12 Answers

78
accepted

Bitwise operators are operators that work on multi-bit values, but conceptually one bit at a time.

  • AND is 1 only if both of its inputs are 1, otherwise it's 0.
  • OR is 1 if one or both of its inputs are 1, otherwise it's 0.
  • XOR is 1 only if exactly one of its inputs are 1, otherwise it's 0.
  • NOT is 1 only if its input is 0, otherwise it's 0.

These can often be best shown as truth tables. Input possibilities are on the top and left, the resultant bit is one of the four (two in the case of NOT since it only has one input) values shown at the intersection of the inputs.

AND | 0 1     OR | 0 1     XOR | 0 1    NOT | 0 1----+-----    ---+----     ----+----    ----+---- 0  | 0 0      0 | 0 1       0 | 0 1        | 1 0 1  | 0 1      1 | 1 1       1 | 1 0

One example is if you only want the lower 4 bits of an integer, you AND it with 15 (binary 1111) so:

201: 1100 1001AND  15: 0000 1111------------------ IS   9  0000 1001

The zero bits in 15 in that case effectively act as a filter, forcing the bits in the result to be zero as well.

In addition, >> and << are often included as bitwise operators, and they "shift" a value respectively right and left by a certain number of bits, throwing away bits that roll of the end you're shifting towards, and feeding in zero bits at the other end.

So, for example:

1001 0101 >> 2 gives 0010 01011111 1111 << 4 gives 1111 0000

Note that the left shift in Python is unusual in that it's not using a fixed width where bits are discarded - while many languages use a fixed width based on the data type, Python simply expands the width to cater for extra bits. In order to get the discarding behaviour in Python, you can follow a left shift with a bitwise and such as in an 8-bit value shifting left four bits:

bits8 = (bits8 << 4) & 255

With that in mind, another example of bitwise operators is if you have two 4-bit values that you want to pack into an 8-bit one, you can use all three of your operators (left-shiftand and or):

packed_val = ((val1 & 15) << 4) | (val2 & 15)
  • The & 15 operation will make sure that both values only have the lower 4 bits.
  • The << 4 is a 4-bit shift left to move val1 into the top 4 bits of an 8-bit value.
  • The | simply combines these two together.

If val1 is 7 and val2 is 4:

val1            val2                ====            ==== & 15 (and)   xxxx-0111       xxxx-0100  & 15 << 4 (left)  0111-0000           |                  |               |                  +-------+-------+                          || (or)                0111-0100
 
1  
bitwise shifts in python are not done modulo any number; ` 0xff << 4 = 0xff0` and similarly 0xffffffff << 32 = 0xffffffff00000000 –   
 
@Hubert, good point, incorporated that into the answer. –   
27

One typical usage:

| is used to set a certain bit to 1

& is used to test or clear a certain bit 

  • Set a bit (where n is the bit number, and 0 is the least significant bit):

    unsigned char a |= (1 << n);

  • Clear a bit:

    unsigned char b &= ~(1 << n);

  • Toggle a bit:

    unsigned char c ^= (1 << n);

  • Test a bit:

    unsigned char e = d & (1 << n);

Take the case of your list for example:

x | 2 is used to set bit 1 of x to 1 

x & 1 is used to test if bit 0 of x is 1 or 0 

 
18

what are bitwise operators actually used for? I'd appreciate some examples.

One of the most common uses of bitwise operations is for parsing hexadecimal colours.

For example, here's a  function that accepts a String like #FF09BE and returns a tuple of its Red, Green and Blue values.

def hexToRgb(value):    //Convert string to hexadecimal number (base 16)    num = (int(value.lstrip("#"), 16))    //Shift 16 bits to the right, and then binary AND to obtain 8 bits representing red    r = ((num >> 16) & 0xFF)    //Shift 8 bits to the right, and then binary AND to obtain 8 bits representing green    g = ((num >> 8) & 0xFF)    //Simply binary AND to obtain 8 bits representing blue    b = (num & 0xFF)    return (r, g, b)

I know that there are more efficient ways to acheive this, but I believe that this is a really concise example illustrating both shifts and bitwise boolean operations.

 
5

I hope this clarifies those two:

x | 20001 //x0010 //20011 //result = 3

x & 10001 //x0001 //10001 //result = 1
 
 
not quite 2 has only one bit set. –   
2  
Oops... tried to be the fastest gun in the west.... ended up as an idiot who doesn't even know binary for two :( Fixed it. –   
1  
x & 1 does not illustrate the effect as well as x & 2 would. –   
3

This example will show you the operations for all four 2 bit values:

10 | 121010 #decimal 101100 #decimal 121110 #result = 14

10 & 121010 #decimal 101100 #decimal 121000 #result = 8

Here is one example of usage:

x = raw_input('Enter a number:')print 'x is %s.' % ('even', 'odd')[x&1]
 
2

Think of 0 as false and 1 as true. Then bitwise and(&) and or(|) work just like regular and and or except they do all of the bits in the value at once. Typically you will see them used for flags if you have 30 options that can be set (say as draw styles on a window) you don't want to have to pass in 30 separate boolean values to set or unset each one so you use | to combine options into a single value and then you use & to check if each option is set. This style of flag passing is heavily used by OpenGL. Since each bit is a separate flag you get flag values on powers of two(aka numbers that have only one bit set) 1(2^0) 2(2^1) 4(2^2) 8(2^3) the power of two tells you which bit is set if the flag is on.

Also note 2 = 10 so x|2 is 110(6) not 111(7) If none of the bits overlap(which is true in this case) | acts like addition.

 
2

I didn't see it mentioned above but you will also see some people use left and right shift for arithmetic operations. A left shift by x is equivalent to multiplying by 2^x (as long as it doesn't overflow) and a right shift is equivalent to dividing by 2^x.

Recently I've seen people using x << 1 and x >> 1 for doubling and halving, although I'm not sure if they are just trying to be clever or if there really is a distinct advantage over the normal operators.

 
1  
I don't know about python, but in lower level languages like C or even lower - assembly, bitwise shift is way much more efficient. To see the difference, you can write a program in C doing this in each way and just compile to assembly code (or if you know assembly lang, you would already know this :) ). See the difference in number of instructions. –   
1  
My argument against using the bit shift operators would be that most modern compilers are probably optimizing arithmetic operations already so the cleverness is at best moot or at worst fighting the compiler. I have no expertise in C, compilers, or CPU designs and so do not presume I am correct. :) –   
2

Bit representations of integers are often used in scientific computing to represent arrays of true-false information because a bitwise operation is much faster than iterating through an array of booleans. (Higher level languages may use the idea of a bit array.)

A nice and fairly simple example of this is the general solution to the game of Nim. Take a look at the  code on . It makes heavy use of bitwise exclusive or, ^.

 
1

I think that the second part of the question: 

Also, what are bitwise operators actually used for? I'd appreciate some examples.

Has been only partially addressed. These are my two cents on that matter. 

Bitwise operations in programming languages play a fundamental role when dealing with a lot of applications. Almost all low-level computing must be done using this kind of operations. 

In all applications that need to send data between two nodes, such as:

  • computer networks;

  • telecommunication applications (cellular phones, satellite communications, etc).

In the lower level layer of communication, the data is usually sent in what is called frames. Frames are just strings of bytes that are sent through a physical channel. This frames usually contain the actual data plus some other fields (coded in bytes) that are part of what is called the header. The header usually contains bytes that encode some information related to the status of the communication (e.g, with flags (bits)), frame counters, correction and error detection codes, etc. To get the transmitted data in a frame, and to build the frames to send data, you will need for sure bitwise operations.

In general, when dealing with that kind of applications, an API is available so you don't have to deal with all those details. For example, all modern programming languages provide libraries for socket connections, so you don't actually need to build the TCP/IP communication frames. But think about the good people that programmed those APIs for you, they had to deal with frame construction for sure; using all kinds of bitwise operations to go back and forth from the low-level to the higher-level communication.

As a concrete example, imagine some one gives you a file that contains raw data that was captured directly by telecommunication hardware. In this case, in order to find the frames, you will need to read the raw bytes in the file and try to find some kind of synchronization words, by scanning the data bit by bit. After identifying the synchronization words, you will need to get the actual frames, and SHIFT them if necessary (and that is just the start of the story) to get the actual data that is being transmitted.

Another very different low level family of application is when you need to control hardware using some (kind of ancient) ports, such as parallel and serial ports. This ports are controlled by setting some bytes, and each bit of that bytes has a specific meaning, in terms of instructions, for that port (see for instance ). If you want to build software that does something with that hardware you will need bitwise operations to translate the instructions you want to execute to the bytes that the port understand.

For example, if you have some physical buttons connected to the parallel port to control some other device, this is a line of code that you can find in the soft application: 

read = ((read ^ 0x80) >> 4) & 0x0f;

Hope this contributes.

 
1

There may be a better way to find where an array element is between two values, but as this example shows, the & works here, whereas and does not.

import numpy as npa=np.array([1.2, 2.3, 3.4])np.where((a>2) and (a<3))      #Result: Value Errornp.where((a>2) & (a<3))#Result: (array([1]),)

转载地址:http://wshbi.baihongyu.com/

你可能感兴趣的文章
zookeeper
查看>>
Idea导入的工程看不到src等代码
查看>>
技术栈
查看>>
Jenkins中shell-script执行报错sh: line 2: npm: command not found
查看>>
8.X版本的node打包时,gulp命令报错 require.extensions.hasownproperty
查看>>
Jenkins 启动命令
查看>>
Maven项目版本继承 – 我必须指定父版本?
查看>>
Maven跳过单元测试的两种方式
查看>>
通过C++反射实现C++与任意脚本(lua、js等)的交互(二)
查看>>
利用清华镜像站解决pip超时问题
查看>>
[leetcode BY python]1两数之和
查看>>
微信小程序开发全线记录
查看>>
Centos import torchvision 出现 No module named ‘_lzma‘
查看>>
Maximum Subsequence Sum
查看>>
PTA:一元多项式的加乘运算
查看>>
CCF 分蛋糕
查看>>
解决python2.7中UnicodeEncodeError
查看>>
小谈python 输出
查看>>
Django objects.all()、objects.get()与objects.filter()之间的区别介绍
查看>>
python:如何将excel文件转化成CSV格式
查看>>