Understanding Bitwise Operators

     

Bitwise operations provide an efficient and concise alternative to tracking large numbers of binary variables ” variables that can have only two values. Using bitwise operators gives you a smaller SWF. In addition, if you often want to set or get multiple values simultaneously , using bitwise operators will probably speed up your program significantly.

Unfortunately, code that incorporates bitwise operators can be hard to read. In addition, to use bitwise operators effectively, you need to understand binary (base 2) arithmetic. Bitwise operators are never an absolute necessity: You can always achieve the same result by using logical (Boolean) operators. Therefore, many programmers avoid bitwise operators. However, bitwise operators are much more concise and efficient for some jobs. You'll almost certainly benefit from having them in your ActionScript toolkit.

Binary arithmetic is based on the bit , which is a unit of information that can have just two states. You can think of these states as 0 and 1, on and off, true and false, set and cleared, or whatever other dichotomy you might want to represent.

ActionScript binary arithmetic is based on 32-bit binary numbers, as shown in Figure A.1. The power of these numbers comes from the fact that you can look at them in two completely different ways:

  • You can get and set them as integers, changing all 32 bits in one operation.

  • You can use each number to represent 31 binary variables, which you can get or set in any grouping or combination you want.

Figure A.1. A 32-bit binary number. The number shown here is 1 because the only digit that is "on" is the ones place.
graphics/ap01fig01.gif

You can switch back and forth between these modes at will, using ordinary arithmetic operators for the first type of operation and the bitwise operators for the second type. It's the second way of looking at binary numbers, in which each digit represents a separate variable, that makes them so powerful in ActionScript.

A Very Short Course in Binary Arithmetic

In base 10, the value of the digits from right to left goes up by powers of 10: 1, 10, 100, 1,000, 10,000, and so on. Each place is 10 times greater than the one to its right. In the binary system, the value of the digits goes up by powers of 2: 1, 2, 4, 8, 16, 32, 64, and so on. Each place is 2 times greater than the one to its right.

This is 1 represented as a 32-bit binary number:

 00000000000000000000000000000001 

This is 2:

 00000000000000000000000000000010 

This is 4:

 00000000000000000000000000000100 

In base 10, each digit can contain a number from 0 to 9. In base 2, each bit can contain either a 0 or a 1. Each place is either on or off. If it's on, you add the value of the place to the number. If it's off, you add nothing.

Consider these examples:

11 in binary is 3: 1x2 + 1x1.

100 in binary is 4: 1x4 + 0x2 + 0x1.

1001 in binary is 9: 1x8 + 0x4 + 0x2 + 1x1.


Figure A.2 shows binary counting from 0 to 8, using four bits. A black oval indicates a 1; a white oval, a 0. At the same time, these bits can be viewed as four on-off switches.

Figure A.2. Binary counting from 0 to 8. The four digits can also be viewed as four on-off switches.

graphics/ap01fig02.gif


With that background, let's look at the bitwise operators. They fall into two basic categories: I'll refer to the first as "bitwise logical." (They're usually just called "bitwise," to avoid confusion with the Boolean logical operators.) The other category is "bit-shift."

In addition, each bitwise logical and bit-shift operator can be combined with an assignment in the same way that arithmetic operators can.

Bitwise Logical Operators

The four bitwise logical operators are AND ( & ), NOT ( ~ ) OR (), and XOR ( ^ ).

The bitwise NOT operator simply reverses every bit of a 32-bit binary number. So, if all the bits of a number are set to 1, they will all be set to 0, and vice versa.

The other three bitwise logical operators compare two 32-bit binary numbers and yield a third 32-bit binary number as a result. They do a bit-by-bit comparison of the two input numbers and use the result of each bitwise comparison to determine the value of the corresponding bit in the third number. You can most easily visualize this comparison by arranging the two input numbers vertically, with the result underneath.

The Bitwise AND Operator

With the bitwise AND operator, the result bit is a 1 only if both input bits are 1. Figure A.3 illustrates this, using four bits. In the figure, only the least significant bit (LSB), bit 0, is a 1 in both input numbers. Therefore, only the LSB is 1 in the result.

Figure A.3. The result bit of the bitwise AND operator is a 1 only if both input bits are 1.

graphics/ap01fig03.gif


NOTE

The symbol for the bitwise AND operator is a single character ( & ), whereas the logical AND operator uses two characters ( && ).


You can use the bitwise AND operator to check whether a particular bit or group of bits is on. For instance, consider this code, which embodies the comparison in Figure A.3:

 x = 13; y = 1; result = x & y; // result is 1 

The result answers the question, "Is the LSB (bit 0) on in x ?" If the result is 1, the LSB is on. If the result is 0, the LSB is off. In this case, it's on.

You could also look at the result the other way around, as answering the question, "Are bits 0, 2, or 3 on in y ?" Whichever bits are on in the result are on in y . In this case, that is just bit 0.

If you set y = 3 , then result = x & y answers the question, "Is either bit 0 or bit 1 on in x ?" Table A.6 shows the possible results and their meanings.

Table A.6. Using the Bitwise AND Operator to Determine the On/Off States of Bits

Result

Bit 1 in x

Bit 0 in x

3

on

on

2

on

off

1

off

on

off

off


For example, in a database of houses for sale, bits 0 and 1 could represent a garage and a carport, respectively. With one query, you could find out whether the house in question has just one or the other (and, if so, which one), or if it has both or neither .

Using two bits, you can check four possible combinations. With three bits, you can check eight combinations. Each additional bit doubles the number of combinations you can check. How many combinations can you check with 31 bits? The answer is 2 to the 31st power, or 2,147,483,648! (Check this result in Flash with trace(Math.pow(2,31)) .) Not bad for four bytes of information.

The Bitwise OR Operator

With the bitwise OR operator, the result bit is a 1 if either input bit is 1, as illustrated in Figure A.4.

Figure A.4. The result bit of the bitwise OR operator is a 1 if either input bit is 1.

graphics/ap01fig04.gif


NOTE

The symbol for the bitwise OR operator is a single character (), whereas the logical OR operator uses two characters ().


You can use the bitwise OR operator to turn on a particular bit or group of bits. For instance, consider this code, which embodies Figure A.4:

 x = 13; y = 1; result = x  y; // result is 13 

Bit 0 will be on in result , no matter what x is. As it happens, bit 0 is already on in x , so there is nothing to turn on, and result and x are the same.

If the bits in operands x and y represent newspaper articles in online databases, the preceding example would represent the question, "Does either database contain the article represented by bit 0?" If bit 0 is on in result , one of the databases has the article. If bit 0 is off in result , neither database has the article.

Another way of thinking about the bitwise OR operator is that it combines two sets of information. For instance, in the example of the two databases, result combines the information in x and y .

The Bitwise XOR Operator

With the bitwise XOR operator, the result bit is a 1 only when the input bits differ , as illustrated in Figure A.5. The symbol for the bitwise XOR operator is the caret ( ^ ) ”Shift+6 on most keyboards.

Figure A.5. The result bit of the bitwise XOR operator is a 1 only when the input bits differ.

graphics/ap01fig05.gif


You can use the bitwise XOR operator to reverse a particular bit or group of bits. For instance, consider this code, which embodies Figure A.5:

 x = 13; y = 1; result = x ^ y; // result = 12, because LSB toggled from 1 to 0 

Bit 0 in result will be reversed from whatever it was in x . In this case, it was on in x , and it is off in result .

If you have on-off buttons in a program, you could track the states of up to 31 buttons in one 32-bit binary number and set the states of multiple buttons simultaneously by using the bitwise XOR operator.

The Bitwise NOT Operator

The bitwise NOT operator reverses each bit of a 32-bit binary number. If you have on-off buttons in a program, for instance, with their on-off states represented in a 32-bit binary number, you could toggle the state of all your buttons in one operation by using the bitwise NOT operator.

Using Multiple Bitwise Logical Operators

You can use multiple bitwise logical operators in a single statement as follows :

 x = 13; y = 1; z = 2; result = x & (y  z); // result = 1 

The final line answers the question, "Is either bit 0 or bit 1 on in x ?" Whichever of these two bits is on in result is also on in x .

Using the same values for x , y, and z as in the preceding example, the following line of code answers the question, "Are both bit 0 and bit 1 on in x ?"

 result = (x & (y  z)) == (y  z); // result is false 

In this case, bit 0 is on in x , but bit 1 is not, so result is false .

To understand the logic of this expression, consider that (y z) is some group of bits; call it g . Then (x & (y z)) is the overlap between x and g ”the bits that are on in both. This means that result answers the question, "Is the overlap between x and g equal to g ?" If so, that is the same as saying that all the on bits in g are also on in x . In this case, y is 1, so bit 0 is on in y ; z is 2, so bit 1 is on in z . So g in this example includes both bits 0 and 1. But x is 13, in which bits 3, 2, and 0 are on, but not bit 1. So the overlap between x and g is only bit 0, which is not equal to g .

Bit-Shift Operators

The three bit-shift operators move the value in each bit a certain number of steps to the right or left. Bits at the end of the line fall off and are lost.

Shifting bits one step to the right is the equivalent of dividing by 2. Shifting bits one step to the left is the equivalent of multiplying by 2.

Shifting bits is analogous to the base-10 phenomenon , in which shifting digits to the right or left divides or multiplies by 10. For instance, if you start with 100 and shift digits one step to the right, you get 10. In other words, you have just divided by 10. The final 0 in 100 falls off and is lost.

Similarly, if you start with binary 100 (which is 4) and shift digits one step to the right, you get binary 10 (which is 2). In this case, you have just divided by 2. The final 0 in the binary 100 falls off and is lost.

Using bit-shift operators to divide or multiply an integer is significantly faster than using the division ( / ) or multiplication ( * ) operators. In some tests that I have run, the difference has been about 30%. Of course, using bit-shift operators to divide or multiply works only if your divisor or multiplier is a power of 2. Also, if you bit-shift right (divide) with an odd operand, the result is rounded down because the LSB falls off. Positive results become smaller, and negative results become more negative.

Signed Right Shift

The signed right shift divides by 2, dropping any remainder. It preserves the sign of a negative number.

Preserving the Sign When Shifting Right

Computers set the most significant bit (MSB) to 1 when making a number negative in " twos complement" notation. In positive numbers, the MSB is 0.

As a binary number is shifted to the right, bits fall off on the right, and new bits appear on the left. For negative numbers, the bitwise signed right shift operator sets the new bits to 1. For positive numbers, it sets the new bits to 0. In this way, the signs of numbers are preserved even if you reverse the process and shift left the same number of steps that you shifted right.


The general form of the signed right shift is

  result  =  value  >>  steps  

NOTE

The symbol for the signed right shift is formed by two greater than signs together: >> .


Consider these examples of the signed right shift:

 x = 10; y = 1; result = x >> y ; // result = 5, which is 10 / 2, no remainder x = 13; y = 2; result = x >> y ; // result = 3, which is 13 / 4, rounded down x = -13; y = 2; result = x >> y ; // result = -4, which is 13 / 4, rounded down 

Unsigned Right Shift

The unsigned right shift shifts digits to the right. However, unlike the signed right shift, the unsigned right shift always adds zeros on the left. Therefore, the result is always positive.

The general form of the unsigned right shift is

  result  =  value  >>>  steps  

NOTE

The symbol for the unsigned right shift is formed by three greater than signs together: >>> .


The unsigned right shift sometimes comes in handy when you're "twiddling bits." However, it doesn't have any obvious arithmetic applications. For positive numbers, it yields the same results as the signed right shift. For negative numbers, the 1s in the high bits yield results that are not related to the original number in any obvious way. For instance:

 x = -13; y = 1; result = x >>> y ; // result = 2,147,483, 641 

Signed Left Shift

The signed left shift multiplies by 2, preserving the sign of a negative number.

The general form of the signed left shift is

  result  =  value  <<  steps  

NOTE

The symbol for the signed left shift is formed by two less than signs together: << .


Consider these examples of the signed left shift:

 x = 13; y = 2; result = x << y ; // result = 52, which is 13 * 4 x = 10; y = 1; result = x << y ; // result = 20, which is 10 * 2 x = -13; y = 2; result = x << y ; // result = -52, which is -13 * 4 



Using Macromedia Studio MX 2004
Special Edition Using Macromedia Studio MX 2004
ISBN: 0789730421
EAN: 2147483647
Year: N/A
Pages: 339

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net