简体   繁体   中英

Python - Confused by if statement if bits&0x20==0x20

I'm confused about the '&' in the below if statement. Is the fist if saying "if bits and 0x10 = 0x10"

def lcd_byte(bits, mode):
  if bits&0x10==0x10:
    GPIO.output(LCD_D4, True)
  if bits&0x20==0x20:
    GPIO.output(LCD_D5, True)
  if bits&0x40==0x40:
    GPIO.output(LCD_D6, True)
   if bits&0x80==0x80:
    GPIO.output(LCD_D7, True)

No, & is bitwise AND , not boolean AND . Bitwise AND works on the binary level, for each individual bit of the operand values.

Thus, with values 1 and 0 you get:

1 & 1 == 1
1 & 0 == 0
0 & 1 == 0
0 & 0 == 0

But with integer values that, in binary, would comprise of multiple bits, the operator works on each bit pair instead:

2 & 1 == 0
2 & 2 == 2

The expression & 0x10 tests if the 5th bit is set:

0b00010000 & 0x10 == 0x10

because 0x10 (hexadecimal), or 16 decimal, is 00010000 in binary. 0x20 is the 6th bit, 0x40 is the 7th, and 0x80 is the left-most or 8th bit.

The code is a little more verbose than needed; when testing against just one bit, the operator will either return 0 or the bit tested against and the == part can be dispensed with:

def lcd_byte(bits, mode):
    if bits & 0x10:
        GPIO.output(LCD_D4, True)
    if bits & 0x20:
        GPIO.output(LCD_D5, True)
    if bits & 0x40:
        GPIO.output(LCD_D6, True)
    if bits & 0x80:
        GPIO.output(LCD_D7, True)

See the Bitwise operations article on Wikipedia for the nitty-gritty details on how bitwise operations work. Python defines several bitwise operators :

  • & : AND
  • | : OR
  • ^ : XOR
  • << : left-shift
  • >> : right-shift

What's happening is that a particular bit of the byte is being tested. For example, suppose the value is 0xAF or in decimal, 175. In binary that is:

bit    7654 3210
----------------
value  1010 1111

Now we want to test to see if bit 5 in the above is set. So we make a mask containing just that bit set. It's called a mask because it's like a stencil, only allowing certain bits to "show through" where there is a 1 in the mask. 0 bits in the mask are "masked off" and we don't care about their values.

bit    7654 3210
----------------   =   0x20 or 32 in decimal
value  0010 0000

Now we can use a bitwise and operation to test the value. By "bitwise" we mean that each bit in one value is tested against the corresponding bit in the other, and by "and" we mean that the resulting bit is set only if the bit is set in both of the original values. In Python this operation is written & .

ORIGINAL VALUE          MASK                    RESULT

bit    7654 3210        bit    7654 3210        bit    7654 3210
----------------   &    ----------------   =    ----------------
value  1010 1111        value  0010 0000        value  0010 0000

Now we look at the result. If the result is non-zero, then we know that the bit was set in the original value.

Now, the Python code you posted actually checks not if it's non-zero, but to see if it's the actual mask value. You only really need to do that if you are testing multiple bits at once, which you can do just by including multiple 1 bits in the mask. In that case, the result is non-zero if any of the corresponding bits are set in the original value. Sometimes that's what you want, but if you want to make sure all of them are set, then you need to explicitly compare the result to the mask value.

In this specific example, each bit corresponds to a specific GPIO output, which is activated when the bit is turned on (presumably these outputs are all turned off at once earlier in the code).

Two things to note here:

  • & is bitwise and , not logical and .
  • & has higher precedence than == , so your expression is parsed as (bits & 0x20) == 0x20 .

The idiom x & mask has the effect of filtering the bits of x such that only the ones which are 1 in the mask are kept.

bits        : b8 b7 b6 b5 b4 b3 b2 b1
0x20        :  0  0  1  0  0  0  0  0
===================================== 
bits & 0x20 :  0  0 b6  0  0  0  0  0

Thus, bits & 0x20 == 0x20 is true precisely when the 6th bit ( b6 ) was 1 in bits .

As written this is a little redundant:

if bits & 0x10 == 0x10: ...

tests whether bit 0x10 is set, which could be expressed more simply as

if bits & 0x10: ...

However, if you need to test more than one bit, it might not be redundant.

if bits & 0x11: ...

tests whether either bit 0x01 or bit 0x10 is set;

if bits & 0x11 == 0x11: ...

tests whether both bits 0x01 and 0x10 are set.

No, it is saying " bits & 0x10" it evaluates that, and then it takes whatever that is and checks if equal to 0x10.

i hate hex bitwise ( to look at its weird) so imma use binary

for example:

if 0b10000 & 0b10000 == 0b10000:

im using 0x11 for example bits

is evaluated as "(0b10001 & 0b10000 ) == 0b10000 " or "0b10000 == 0b10000 " if you simplify or just "True" if you simplify further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM