• Aucun résultat trouvé

The Bit-Manipulation Operators

Dans le document Teach Yourself Perl 5 in 21 days (Page 124-129)

The following bit-manipulation operators are supported in Perl:

The & (bitwise AND) operator

The | (bitwise OR) operator

The ^ (bitwise XOR or "exclusive or") operator

The ~ (bitwise NOT) operator

The << (left shift) and >> (right shift) operators

The Bitwise AND Operator

In Perl, the & operator represents the bitwise AND operation. This operation works as follows:

The value to the left side of the & (also called the left operand of the & operation) is converted to an integer, if necessary.

The value to the right side of the & (the right operand) also is converted to an integer.

Each bit of the left operand is compared to the corresponding bit of the right operand.

If a pair of corresponding bits both have the value 1, the corresponding bit of the result is set to 1. Otherwise, the corresponding bit of the result is set to 0.

This might sound complicated, but when you take a look at an example, you'll see that it's pretty easy to figure out. For instance, consider the following:

$result = 124.3 & 99;

First, the left operand, 124.3, is converted to an integer, becoming 124. (The right operand, 99, does not need to be converted.) Next, take a look at the binary representations of 124 and 99:

01111100 # this is 124 in binary 01100011 # this is 99 in binary

When you examine each pair of bits in turn, you can see that only the second and third pairs (from the left) are both 1. Thus, the &

operation yields the following binary result:

01100000

This is 96 in standard notation. As a consequence, the statement

$result = 124.3 & 99;

assigns 96 to $result.

DO use the & operator with strings, provided the strings can be converted to numbers, as follows:

$result = "124.3" & "99";

Remember: Strings and integers are interchangeable in Perl.

DON'T confuse the & operator with the && operator. The && operator performs a logical AND operation, not a bitwise AND operation. For example, the statement

$result = 124.3 && 99;

assigns a nonzero value to $result (because 124.3 and 99 are both nonzero). This nonzero value is not likely to be the result you want.

DON'T use the & operator with negative integers, because Perl will convert them to unsigned integers, and you won't get the result you want.

The Bitwise OR Operator

The bitwise OR operator, |, also compares two integers one bit at a time. However, in the bitwise OR operation, a result bit is 1 if either of the corresponding bits in the operands is 1.

To see how this works, look at another example:

$result = 124.3 | 99;

Here's how this operation is performed:

As before, the two operands are converted to integers if necessary. The operands become 124 and 99; in binary representation, these are, as before,

01111100 01100011

Each bit of the left operand is compared with the corresponding bit in the right operand. If either of the corresponding bits is 1, the corresponding result bit is 1.

In this example, every bit becomes 1 except the first one, because at least one of each of the other pairs is a 1. Therefore, the result is

01111111

which translates to 127. This means that the following statement assigns 127 to $result:

$result = 124.3 | 99;

DO make sure you are using the proper bitwise operator. It's easy to slip and assume you want bitwise OR when you really want bitwise AND. (Trust me.)

DON'T confuse the | operator (bitwise OR) with the || operator (logical OR).

The Bitwise XOR Operator

The bitwise XOR ("exclusive or") operator, ^, is similar to the bitwise OR operator, but it's a little more demanding. In the bitwise OR operation, a result bit is 1 if either of the corresponding bits in the operands is 1. In the bitwise XOR operation, a result bit is 1 if exactly one of the corresponding bits in the operands is 1.

Here is an example of the bitwise XOR operation:

$result = 124.3 ^ 99;

This works as follows:

As before, 124.3 is converted to 124, and the binary representations of the two operands are as follows:

01111100 # this is 124 01100011 # this is 99

Each bit of the left operand is compared with the corresponding bit of the right operand. The corresponding result bit is set to 1 if exactly one of the bits in the operands is 1.

In this case, the result is

00011111

which is 31. To work through how you get this result, consider the following:

The first bit of the left operand and the first bit of the right operand are both 0. This means the first bit of the result is 0.

The second bit of the left operand and the second bit of the right operand both are 1. Therefore, the second bit of the result is 0, not 1.

The same applies for the third bits: Both are 1, so the result bit is 0.

The fourth bit of the left operand is 1, and the fourth bit of the right operand is 0. Here, exactly one of the bits is 1, so the result bit becomes 1.

Same for the fifth and sixth pairs: The first bit is 1 and the second is 0, so the result is 1.

The seventh bit of the left operand is 0, and the seventh bit of the right operand is 1. Again, exactly one of the bits is 1, and the result bit is also 1.

Same for the eighth pair: The first bit is 0, the second is 1, so the result is 1.

From this, you can determine that the following statement assigns 31 to $result:

$result = 124.3 ^ 99;

The Bitwise NOT Operator

Unlike the other bitwise operators you've seen so far, the bitwise NOT operator, ~, is a unary operator, meaning it works on only one operand.

The way it works is straightforward, as follows:

The operand is converted to an integer, if necessary.

Each bit of the operand is examined. If a bit is 0, the corresponding result bit is set to 1, and vice versa.

For example, consider the following:

$result = ~99;

The binary representation of 99 is

01100011

Applying the bitwise NOT operation to this number produces

10011100

This number, in standard notation, is 156. Therefore, the following statement assigns 156 to $result:

$result = ~99;

Note that the number of bits used to store an integer affects the results produced by the ~ operator. For example, if integers are stored in 16 bits on your computer, the number 99 is represented as

0000000001100011

This means that applying ~ to this number yields

1111111110011100

which is 65436 in standard notation. As a consequence, the statement

$result = ~99;

assigns 65436, not 156, to $result. (On a computer with 32-bit integers, the value assigned is 4294967196.) The Shift Operators

Perl enables you to shift the bits of an integer using the << (shift left) and >> (shift right) operators. For example, in the statement

$result = $x >> 1;

every bit of the value stored in $x is shifted one place to the right, and the result is assigned to $result ($x itself is not changed).

To see how this works, consider the following example:

$result = 99 >> 1;

As you saw earlier, the binary representation of 99 is

01100011

Shifting every bit right one place yields

00110001

Note that a 0 is added at the far left, and the bit at the far right disappears.

Because 00110001 in binary notation is the same as 49 in standard notation, the following statement assigns 49 to $result:

$result = 99 >> 1;

The <<, or shift-left, operator works in the same way:

$result = 99 << 1;

The shift-left operator works as follows:

01100011 # the binary representation of 99 11000110 # after shifting left 1 bit

The result of the shift is 198, which is assigned to $result.

DO remember that when you use the >> operator, the bits on the right are lost. For example:

$result1 = 17 >> 1;

$result2 = 16 >> 1;

In this case, $result1 and $result2 are the same value, 8. This is because the rightmost bit is shifted out in both cases.

DON'T shift left too far, or you might not get the result you want. For example, if you are using 16-bit integers, the statement

$result = 35000 << 1;

does not assign 70000 to $result as you might think it would because the largest value that can be stored in a 16-bit integer is 65536.

Shifting and Powers of 2

In the following statement, the variable $result is assigned the value 49:

$result = 99 / 2;

Take a look at the binary representations of 99 and 49:

01100011 # 99 in binary form

00110001 # 49 in binary form

As you can see, dividing by 2 is identical to shifting right one bit-in each case, every bit is moved one place to the right. Similarly, shifting right two bits is equivalent to dividing by 4:

$result = 99 / 4; # $result is assigned 24 01100011 # 99 in binary

00011000 # 24 in binary

Multiplying by 4 is similar to shifting left two bits:

$result = 17 * 4; # $result is assigned 68 00010001 # 17 in binary

01000100 # 68 in binary

The general rules are as follows:

Shifting left n bits, where n is some number greater than 0, is equivalent to multiplying by 2**n.

Shifting right n bits, where n is some number greater than 0, is equivalent to dividing by 2**n.

In the early days of programming, many programmers used shift operators in place of multiplication and division wherever possible, because the shift operations were usually more efficient. (In fact, some compilers would optimize their code by

converting multiplication and division to shifts.) Today, it's usually best to use the shift operators when you are manipulating bits, and to use the multiplication and division operators when you're actually doing arithmetic. This will make your programs easier to understand.

Dans le document Teach Yourself Perl 5 in 21 days (Page 124-129)