Previous Page Next Page

6.3. Precedence and Associativity

When an expression contains a number of operators and operands, and the result of the operation is potentially ambiguous, the order of precedence and associativity tells you how the compiler evaluates such an expression. Precedence refers to the way in which the operator binds to its operand. The multiplication operator binds more tightly to its operands than the addition operator, so it is of higher precedence, whereas the assignment operators are low in precedence and thus bind loosely to their operands.[2] Parentheses are of the highest precedence and are used to control the way an expression is evaluated. When parentheses are nested, the expression contained within the innermost set of parentheses is evaluated first.

[2] An easy rule to remember precedence: Please Excuse My Dear Aunt Sally, which stands for Parentheses, Exponentiation, Multiplication, Division, Addition, and Subtraction.

Associativity refers to the order in which an operator evaluates its operands: left to right, in no specified order, or right to left.

In the following example, how is the expression evaluated? Is addition, multiplication, or division done first? And in what order—right to left or left to right?

Example 6.2.

(The Script)
1   $x = 5 + 4  * 12 / 4;
2   print "The result is  $x\n";

(Output)
2   The result is 17

Explanation

  1. The order of associativity is from left to right. Multiplication and division are of a higher precedence than addition and subtraction, and addition and subtraction are of higher precedence than assignment. To illustrate this, we'll use parentheses to group the operands as they are handled by the compiler. In fact, if you want to force precedence, use the parentheses around the expression to group the operands in the way you want them evaluated.

    $x = (5 + ( ( 4 * 12 ) / 4));
  2. The expression is evaluated and the result is printed to STDOUT.

Table 6.2 summarizes the rules of precedence and associativity for the Perl operators. The operators on the same line are of equal precedence. The rows are in order of highest to lowest precedence.

Table 6.2. Precedence and Associativity
OperatorDescriptionAssociativity
() [ ] { }Function call, array subscriptsLeft to right
>Dereferencing operatorLeft to right
++ - -Autoincrement, autodecrementNone
**ExponentiationRight to left
! ~ \ + -Logical not, bitwise not, backslash, unary plus, unary minusRight to left
=~ !~Match and not matchLeft to right
* / % xMultiply, divide, modulus, string repetitionLeft to right
+ -.Add, subtract, string concatenationLeft to right
<< >>Bitwise left shift, right shiftLeft to right
-r -w -x -o etc.Named unary operators; e.g., file test operatorsNone
< <= > >= lt le gt geNumeric and string tests; e.g., less than, greater than, etc.None
== != <=> eq ne cmpNumeric and string tests; e.g., equal to, not equal to, etc.None
&Bitwise andLeft to right
| ^Bitwise or, exclusive or (xor)Left to right
&&Logical andLeft to right
||Logical orLeft to right
..Range operatorNone
? :Ternary, conditionalRight to left
= += -= *= /= %=AssignmentRight to left
, =>Evaluate left operand, discard it, and evaluate right operandLeft to right
notSynonym for ! with lower precedenceRight
andSynonym for &&Left to right
or xorSynonym for ||, ^Left to right


6.3.1. Assignment Operators

The = sign is an assignment operator. The value on the right-hand side of the equal sign is assigned to the variable on the left-hand side. Table 6.3 illustrates assignment and shortcut assignment statements borrowed from the C language.

Table 6.3. Assignment Operators
OperatorExampleMeaning
=$var = 5;Assign 5 to $var
+=$var += 3;Add 3 to $var and assign result to $var
-=$var -= 2;Subtract 2 from $var and assign result to $var
.=$str.="ing";Concatenate ing to $str and assign result to $str
*=$var *= 4;Multiply $var by 4 and assign result to $var
/=$var /= 2;Divide $var by 2 and assign result to $var
**=$var **= 2;Square $var and assign result to $var
%=$var %= 2;Divide $var by 2 and assign remainder to $var
x=$str x= 20;Repeat value of $str 20 times and assign result to $str
<<=$var <<= 1;Left-shift bits in $var one position and assign result to $var
>>=$var>>= 2;Right-shift bits in $var two positions and assign result to $var
&=$var &= 1;One is bitwise-ANDed to $var and the result is assigned to $var
|=$var |= 2;Two is bitwise-ORed to $var and the result is assigned to $var
^=$var ^= 2;Two is bitwise-exclusive ORed to $var and the result is assigned to $var


Example 6.3.

(The Script)
    #!/usr/bin/perl
1   $name="Dan";
    $line="*";
    $var=0;       # Assign 0 to var

2   $var += 3;    # Add 3 to $var; same as $var=$var+3
    print  "\$var += 3 is $var \n";

3   $var -= 1;    # Subtract 1 from $var
    print "\$var -= 1 is $var\n";

4   $var **= 2;        # Square $var
    print "\$var squared is $var\n";

5   $var %= 3;         # Modulus
    print "The remainder of \$var/3 is $var\n";

6   $name .= "ielle";  # Concatenate string "Dan" and "ielle"
    print "$name is the girl's version of Dan.\n";
7   $line x= 10;       # Repetition; print 10 stars
    print "$line\n";

8   printf "\$var is %.2f\n", $var=4.2 + 4.69;

(Output)
2   $var += 3 is 3
3   $var -=1 is 2
4   $var squared is 4
5   The remainder of $var/3 is 1
6   Danielle is the girl's version of Dan.
7   **********
8   $var is 8.89

					  

Explanation

  1. Values on the right-hand side of the equal sign are assigned to scalar variables on the left-hand side of the equal sign.

  2. The shortcut assignment operator, +=, adds 3 to the scalar $var. This is equivalent to $var = $var + 3;

  3. The shortcut assignment operator, -=, subtracts 1 from the scalar $var. This is equivalent to $var = $var - 1;

  4. The shortcut assignment operator, **, squares the scalar $var. This is equivalent to $var = $var ** 2;

  5. The shortcut assignment modulus operator, %, yields the integer amount that remains after the scalar $var is divided by 3. The operator is called the modulus operator, or remainder operator. The expression $var% = 3 is equivalent to $var = $var % 3;.

  6. The shortcut assignment operator, ., concatenates the string "ielle" to the string value of the scalar, $name. This is equivalent to $name = $name . "ielle".

  7. The repetition operator takes two operands. The operand on the right is the number of times the string operand on the left is repeated. The value of the scalar $line, an asterisk (*), is repeated 10 times.

  8. The printf function is used to format and print the result of the addition of two floating point numbers.

6.3.2. Relational Operators

Relational operators are used to compare operands. The result of the comparison is either true or false.[3] Perl has two classes of relational operators: one set that compares numbers and another that compares strings. Normally, these operators are used to test a condition when using if/else, while loops, etc., as follows:

[3] As in other languages, Perl doesn't support a Boolean data type where "true" and "false" are keywords that evaluate to either 1 or 0. However, any nonzero number can be used in an expression to represent true, and ! 1 is used to represent false; e.g., while( 1 ) or if ! 1....

     if ( $x > $b ){ print "$x is greater.\n"; }

We will discuss conditionals in Chapter 7.

The expression (5 > 4 > 2) will produce a syntax error because there is no associativity. (See Table 6.2.)

Numeric

Table 6.4 contains a list of numeric relational operators.

Table 6.4. Relational Operators and Numeric Values
OperatorExampleMeaning
>$x > $y$x is greater than $y
>=$x >= $y$x is greater than or equal to $y
<$x < $y$x is less than $y
<=$x <= $y$x is less than or equal to $y


Example 6.4.

(The Script)
    $x = 5;
    $y = 4;
1   $result = $x > $y;
2   print "$result\n";

3   $result = $x < $y;
4   print $result;

(Output)
2   1
4   0

Explanation

  1. If $x is greater than $y, the value 1 (true) is returned and stored in $result; otherwise, 0 (false) is returned.

  2. Since the expression was true, the value of $result, 1, is printed to STDOUT.

  3. If $x is less than $y, the value 1 (true) is returned and stored in $result; otherwise, 0 (false) is returned.

  4. Since the expression was false, the value of $result, 0, is printed to STDOUT.

String

The string relational operators evaluate their operands (strings) by comparing the ASCII value of each character in the first string with the corresponding character in the second string. The comparison includes trailing whitespace.

If the first string contains a character that is of a higher or lower ASCII value than the corresponding character in the second string, the value 1 is returned; otherwise, 0 is returned.

Table 6.5 contains a list of relational string operators.

Table 6.5. Relational Operators and String Values
OperatorExampleMeaning
gt$str1 gt $str2$str1 is greater than $str2
ge$str1 ge $str2$str1 is greater than or equal to $str2
lt$str1 lt $str2$str1 is less than $str2
le$str1 le $str2$str1 is less than or equal to $str2


Example 6.5.

(The Script)
1   $fruit1 = "pear";
2   $fruit2 = "peaR";
3   $result = $fruit1 gt $fruit2;
4   print "$result\n";

5   $result = $fruit1 lt $fruit2;
6   print "$result\n";

(Output)
4   1
6   0

Explanation

  1. The scalar $fruit1 is assigned the string value pear.

  2. The scalar $fruit2 is assigned the string value peaR.

  3. When lexographically comparing each of the characters in $fruit1 and $fruit2, all of the characters are equal until the r and R are compared. The ASCII value of the lowercase r is 114, and the ASCII value of the uppercase R is 82. Since 114 is greater than 82, the result of evaluating the strings is 1 (true); i.e., pear is greater than peaR.

  4. Since the expression was true, the value of $result, 1, is printed to STDOUT.

  5. This is the reverse of #3. The ASCII value of uppercase R (82) is less than the value of the lowercase r (114). The result of evaluating the two strings is 0 (false); i.e., pear is less than peaR.

  6. Since the expression was false, the value of $result, 0, is printed to STDOUT.

6.3.3. Equality Operators

The equality operators evaluate numeric operands and string operands. (See Tables 6.6 and 6.7.) Be sure if you are testing equality that you use the string operators for strings and the numeric operators for numbers! If, for example, you have the expression:

     "5 cats" == "5 dogs"

Table 6.6. Equality Operators and Numeric Values
OperatorExampleMeaning
==$num1 == $num2$num1 is equal to $num2
!=$num1 != $num2$num1 is not equal to $num2
<=>$num1 <=> $num2$num1 is compared to $num2 with a signed return; 1 if $num1 is greater than $num2, 0 if $num1 is equal to $num2, and -1 if $num1 is less than $num2


Table 6.7. Equality Operators and String Values
OperatorExampleMeaning
eq$str1 eq $str2$str1 is equal to $str2
ne$str1 ne $str2$str1 is not equal to $str2
cmp$str1 cmp $str2$str1 is compared to $str2, with a signed return


the expression will evaluate to true. Why? Because Perl sees a numeric operator, ==. The == operator expects its operands to be numbers, not strings. Perl will then convert the "5 cats" to a number 5 and the string "5 dogs" to the number 5, resulting in 5 == 5, which evaluates to true. (In the conversion, Perl starts on the left-hand side of the string and looks for a number; if there is a number, Perl keeps it. As soon as a non-number is found, the conversion stops.)

Numeric

The numeric equality operators evaluate their operands (numbers) by comparing their numeric values. If the operands are equal, 1 (true) is returned; if the operands are not equal, 0 (false) is returned.

The numeric comparison operator evaluates its operands, returning a -1 if the first operand is less than the second operand, 0 if the numbers are equal, or 1 if the first operand is greater than the second.

Example 6.6.

(The Script)
    $x = 5;
    $y = 4;
1   $result = $x == $y;
2   print "$result\n";

3   $result = $x != $y;
4   print "$result\n";
5   $result = $x <=> $y;
6   print "$result\n";

7   $result = $y <=> $x;
8   print "$result\n";

(Output)
2   0
4   1
6   1
8   -1

Explanation

  1. If $x is equal to $y, the value 1 (true) is returned and stored in $result; otherwise, 0 (false) is returned.

  2. Since the expression was not true, the value of $result, 0, is printed to STDOUT.

  3. If $x is not equal to $y, the value 1 (true) is returned and stored in $result; otherwise, 0 (false) is returned.

  4. Since the expression was true, the value of $result, 1, is printed to STDOUT.

  5. The scalars, $x and $y, are compared. If $x is greater than $y, 1 is returned; if $x is equal to $y, 0 is returned; if $x is less than $y, a signed -1 is returned.

  6. Since $x is greater than $y, the value of $result, 1, is printed to STDOUT.

  7. The scalars $x and $y are compared. If $y is greater than $x, 1 is returned; if $x is equal to $y, 0 is returned; if $y is less than $x, a signed -1 is returned.

  8. Since $x is less than $y, the value of $result, -1, is printed to STDOUT.

String

The string equality operators evaluate their operands (strings) by comparing the ASCII value of each character in the first string with the corresponding character in the second string. The comparison includes trailing whitespace.

If the first string contains a character that is of a higher ASCII value than the corresponding character in the second string, the value 1 is returned; if the strings are equal, 0 is returned; if the first string character has a lesser ASCII value than the corresponding character in the second string, -1 is returned. (See Table 6.7.)

Example 6.7.

(The Script)
1   $str1 = "A";
    $str2 = "C";
    $result = $str1 eq $str2;
    print "$result\n";

2   $result = $str1 ne $str2;
    print "$result\n";

3   $result = $str1 cmp $str2;
    print "$result\n";

4   $result = $str2 cmp $str1;
    print "$result\n";

5   $str1 = "C";       # Now both strings are equal
6   $result = $str1 cmp $str2;
    print "$result\n";

(Output)
1   0
2   1
3   -1
4   1
6   0

Explanation

  1. The scalar $str1 is assigned the value A, and scalar $str2 is assigned the value C. If $str1 is equal to $str2, the value 1 (true) is returned, assigned to $result, and printed.

  2. If $str1 is not equal to $str2, the value 1 (true) is returned, assigned to $result, and printed.

  3. If $str1 is compared with $str2 (i.e., an ASCII comparison is made on each character), and all characters are the same, the value 0 is returned and assigned to $result. If $str1 is greater than $str2, the value 1 is returned, and if $str1 is less than $str2, -1 is returned. In this example, $str1 is less than $str2. The value of $result is printed.

  4. In this example, we reverse the order of comparison. Since $str2 is greater than $str1, the result is 1. The value of $result is printed.

  5. $str1 is assigned C. It has the same value as $str2.

  6. Now $str1 and $str2 are equal. Since all of the characters are the same, the value 0 is returned and assigned to $result. The value of $result is printed.

Example 6.8.

(The Script)
    # Don't use == when you should use eq!
1   $x = "yes";
    $y = "no";
    print "\nIs yes equal to no? If so, say 1; if not say 'null'.\n";
2   print "The result is: ",$x == $y,"\n";    # Should be $x eq $y

(Output)
1   Is yes equal to no? If so, say 1; if not say 'null'.
2   The result is: 1

Explanation

  1. The scalars $x and $y are assigned string values yes and no, respectively.

  2. The numeric equality operator, ==, is being used incorrectly to test the equality of two strings. The strings are converted to numbers. Since the characters are nonnumeric, the result is to convert each string to 0 (zero). 0 is equal to 0, resulting in 1 (true). The string equality operator eq should have been used in this test.

6.3.4. Logical Operators (Short-Circuit Operators)

The short-circuit operators evaluate their operands, from left to right, testing the truth or falsity of each operand in turn. There is no further evaluation once a true or false condition is satisfied. Unlike C, the short-circuit operators do not return 0 (false) or 1 (true) but rather the value of the last operand evaluated. These operators are most often used in conditional statements. (See Chapter 7, "If Only, Unconditionally, Forever.")

If the expression on the left-hand side of the && evaluates to 0, the expression is false and 0 is returned. If the expression on the left-hand side of the operator evaluates to true (nonzero), the right-hand side is evaluated and its value is returned.

The logical operators can also be represented as and, or, or not, but the precedence for them is lower. See Table 6.2 on page 140. If the expression on the left-hand side of the || operator is evaluated as true (nonzero), the value of the expression is returned. If the value on the left-hand side of the || is false, the value of the expression on the right-hand side of the operator is evaluated, and its value is returned.

A list of logical operators can be found in Table 6.8.

Table 6.8. Logical Operators (Short-Circuit Operators)
OperatorAlternative FormExampleMeaning
&&and$x && $yIf $x is true, evaluate $y and return $y
  $x and $yIf $x is false, evaluate $x and return $x
||or$x || $yIf $x is true, evaluate $x and return $x
  $x or $yIf $x is false, evaluate $y and return $y
 xor$x xor $yTrue if $x or $y is true, but not both
!not! $xNot $x; true if $x is not true
  not $x 


Example 6.9.

(The Script)
    #!/usr/bin/perl
    # Short-circuit operators
1   $num1=50;
2   $num2=100;
3   $num3=0;

4   print $num1 && $num3, "\n";    # result is 0
5   print $num3 && $num1, "\n";    # result is 0
6   print $num1 && $num2, "\n";    # result is 100
7   print $num2 && $num1, "\n\n";  # result is 50

8   print $num1 || $num3, "\n";    # result is 50
9   print $num3 || $num1, "\n";    # result is 50
10  print $num1 || $num2, "\n";    # result is 50
11  print $num2 || $num1, "\n";    # result is 100

(Output)
4   0
5   0
6   100
7   50
8   50
9   50
10  50
11  100

					  

Explanation

  1. The scalar $num1 is assigned the value 50.

  2. The scalar $num2 is assigned the value 100.

  3. The scalar $num3 is assigned the value 0.

  4. Since the expression to the left of the && operator, $num1, is nonzero (true), the expression to the right of the &&, $num3, is returned.

  5. Since the expression to the left of the && operator, $num3, is zero (false), the expression $num3 is returned.

  6. Since the expression to the left of the && operator, $num1, is true (true), the expression on the right-hand side of the && operator, $num2, is returned.

  7. Since the expression to the left of the && operator, $num2, is true (true), the expression on the right-hand side of the && operator, $num1, is returned.

  8. Since the expression to the left of the || operator, $num1, is nonzero (true), the expression $num1 is returned.

  9. Since the expression to the left of the || operator, $num3, is zero (false), the expression to the right of the || operator, $num1, is returned.

  10. Since the expression to the left of the || operator, $num1, is nonzero (true), the expression $num1 is returned.

  11. Since the expression to the left of the ||operator, $num2, is nonzero (true), the expression $num2 is returned.

6.3.5. Logical Word Operators

These logical operators are of lower precedence than the short-circuit operators but basically work the same way and make the program easier to read and also short-circuit. In addition to the short-circuit operators, the xor (exclusive or) operator has been added to the logical word operators.

Example 6.10.

    # Examples using the word operators
1   $num1=50;
    $num2=100;
    $num3=0;
    print "\nOutput using the word operators.\n\n";
2   print "\n$num1 and $num2: ",($num1 and $num2);, "\n";
3   print "\n$num1 or $num3: ", ($num1 or $num3), "\n";
4   print "\n$num1 xor $num3: ",($num1 xor $num3), "\n";
5   print "\nnot $num3: ", not $num3;
    print "\n";

(Output)
    Output using the word operators.

2   50 and 100: 100

3   50 or 0: 50

4   50 xor 0: 1

5   not 0: 1

Explanation

  1. Initial values are assigned to $num1, $num2, and $num3.

  2. The and operator evaluates its operands. $num1 and $num2 are both true, resulting in the value of the last expression evaluated, 100. Since 100 is a nonzero value, the expression is true.

  3. The or operator evaluates its operands. $num1 is true. The word operators also short-circuit, so that if the first expression is true, there is no need to continue evaulating. The result returned is 50, which is true.

  4. The exclusive xor operator evaluates both its operands. It does not short-circuit. If one of the operands is true, then the expression is true and 1 is returned; if both sides are either true or false, the result is false.

  5. The logical not operator evaluates the operand to the right; if it is true, false is returned if false, true is returned.

Example 6.11.

   (The Script)
    # Precedence with word operators and short-circuit operators
    $x=5;
    $y=6;
    $z=0;
1   $result=$x && $y && $z;       # Precedence of = lower than &&
    print "Result: $result\n";

2   $result2 = $x and $y and $z;  # Precedence of = higher than and
    print "Result: $result2\n";

3   $result3 = ( $x and $y and $z );
    print "Result: $result3\n";

(Output)
1   Result: 0
2   Result: 5
3   Result: 0

Explanation

  1. The logical short-circuit operators evaluate each of the expressions and return the value of the last expression evaluated. The value 0 is assigned to $result. Since && is higher in precedence than the equal sign, the logical operators evaluated their expressions first.

  2. The word operators are used here, but they are lower in precedence than the equal sign. The first expression to the right of the equal sign is assigned to $result2.

  3. By adding parentheses to the expression on the right-hand side of the equal sign, that expression is evaluated first and the result assigned to $result3.

6.3.6. Arithmetic Operators

Perl's arithmetic operators are listed in Table 6.9.

Table 6.9. Arithmetic Operators
OperatorExampleMeaning
+$x + $yAddition
-$x - $ySubtraction
*$x * $yMultiplication
/$x / $yDivision
%$x % $yModulus
**$x ** $yExponentiation


Example 6.12.

(The Script)
1   printf "%d\n", 4 * 5 / 2;
2   printf "%d\n", 5 ** 3;
3   printf "%d\n", 5 + 4 - 2 * 10;
4   printf "%d\n", (5 + 4 - 2 ) * 10;
5   printf "%d\n", 11 % 2;

(Output)
1   10
2   125
3   -11
4   70
5   1

Explanation

  1. The printf function formats the result of arithmetic expression in decimal. Multiplication and division are performed. Operators are of the same precedence, left to right associativity. Same as: ( 4 * 5) / 2.

  2. The printf function formats the result of arithmetic expression in decimal. The exponentiation operator cubes its operand, 5, same as 53.

  3. The printf function formats the result of arithmetic expression in decimal. Since the multiplication operator is of higher precedence than the addition and subtraction operators, multiplication is performed first, left to right associativity. Same as: 5 + 4 - (2 * 10).

  4. The printf function formats the result of arithmetic expression in decimal. Since the parentheses are of highest precedence, the expression enclosed in parentheses is calculated first.

  5. The printf function formats the result of arithmetic expression in decimal. The modulus operator produces the remainder after performing division on its operands. (See "The printf Function" on page 59.)

6.3.7. Autoincrement and Autodecrement Operators

The autoincrement operator and autodecrement operators are taken straight from the C language (see Table 6.10). The autoincrement operator adds 1 to the value of a variable, and the autodecrement operator subtracts 1 from the value of a variable. When used with a single variable, these operators are just a shortcut for the traditional method of adding and subtracting 1. However, if used in an assignment statement or if combined with other operators, the end result depends on the placement of the operator. (See Table 6.11.)

Table 6.10. Autoincrement and Autodecrement Operators
ExampleDescriptionEquivalence
++$xPreincrement$x = $x + 1
$x++Postincrement$x = $x + 1
--$xPredecrement$x = $x - 1
$x--Postdecrement$x = $x - 1


Table 6.11. Autoincrement and Autodecrement Operators and Assignment
ExampleDescriptionEquivalenceResult
If $y is 0 and $x is 0: $y = $x++;Assign the value of $x to $y, then increment $x$y = $x; $x = $x + 1;$y is 0 $x is 1
If $y is 0 and $x is 0: $y = ++$x;Increment $x, then assign $x to $y$x = $x + 1; $y = $x;$x is 1 $y is 1
If $y is 0 and $x is 0: $y = $x--;Assign the value of $x to $y, then decrement $x$y = $x; $x = $x - 1;$y is 0 $x is -1
If $y is 0 and $x is 0: $y = --$x;Decrement $x, then assign $x to $y$x = $x - 1; $y = $x;$x is -1 $y is -1


Example 6.13.

(The Script)
    #!/usr/bin/perl
1   $x=5; $y=0;
2   $y=++$x;     # Add 1 to $x first; then assign to $y
3   print "Pre-increment:\n";
4   print "y is $y\n";
5   print "x is $x\n";
6   print  "-----------------------\n";
7   $x=5;
8   $y=0;
9   print "Post-increment:\n";
10  $y=$x++;     # Assign value in $x to $y; then add 1 to $x
11  print "y is $y\n";
12  print "x is $x\n";

(Output)
3   Pre-increment:
4   y is 6
5   x is 6
    -----------------------
9   Post-increment
11  y is 5
12  x is 6

					  

Figure 6.2. Pre- and post-increment operators.


6.3.8. Bitwise Logical Operators

A Little Bit about Bits

People represent numbers in decimal, or base 10, a numbering system based on 10 values starting from 0 to 9; e.g., $100,00 and 1955. The HTML color codes are represented in hexadecimal, base 16, values ranging from 0 to 15; e.g., #00FFFF is cyan and #FF00FF is fuschia. Computers store everything in binary, or base 2. A binary numbering system represents numbers in two values, 0 or 1. Each of the individual 1s and 0s are called bits. All the data you use is stored in your computer using bits. A byte is made up of 8 bits, a word is 2 bytes, or 16 bits, and finally, two words together are called a double word, or dword, which is a 32-bit value. The reason a computer uses only 0s and 1s for everything is because a binary digit is represented by the presence of an electric current. If the level of electricity reaches a certain level, the digit is 1. Otherwise, the digit is a 0. Using just two numbers makes building hardware less difficult and cheaper than if electrical levels were represented by a bigger combination of bits, like base 10 (decimal) or base 16 (hexadecimal). Hence, computers store everything in binary.

Bitwise Operators

Most processors today are built to operate on 32-bit numbers. For example, the term Win32 is derived from the fact that an integer on a Win32 compiler defaults to 32 bits. Bitwise operators allow you to turn specific bits within an integer on or off. For example, if you are setting a read-only flag on a file, you need only two values, on or off, represented as 1 or 0. And if both the left- and right-hand parameters are strings, the bitwise operator will operate on the characters within the string.

Bitwise operators treat their operands as a set of 32 bits (0s and 1s), rather than as decimal, hexadecimal, or octal numbers. For example, the decimal number 9 has a binary representation of 1001. Although bitwise operators perform their operations on bits rather than expressions, they return standard Perl numerical values as shown in Example 6.13. If you are working with graphics, games, encryption, registers, setting switches, etc., or any operation that requires "twiddling bits," then the bitwise operators may become useful. Generally speaking, those types of operations are more fitting for higher-level languages like C or Java.

When you're ready to manipulate integer values at the bit level, the bitwise logical operators are used. The bitwise operators are binary operators and manipulate their operands in terms of the internal binary representation of those operands. A bit-by-bit comparison is made on each of the corresponding operands, producing its result as the binary value (see Tables 6.12 and 6.13).

Table 6.12. Bitwise Logical Operators
OperatorExampleMeaning
&$x & $yBitwise and
|$x | $yBitwise or
^$x ^ $yBitwise exclusive or
<<$x << 1Bitwise left shift, integer multiply by two
>>$x >> 1Bitwise right shift, integer divide by two


Table 6.13. Resulting Values of Bitwise Operators
$x$y$x & $y$x | $y$x ^ $y
00000
01011
10011
11110


Example 6.14.

(The Script)
1   print 5 & 4,"\n";       # 101 & 100
2   print 5 & 0,"\n";       # 101 & 000
3   print 4 & 0,"\n";       # 100 & 000
4   print 0 & 4,"\n";       # 000 & 100
5   print "=" x 10,"\n";    # print 10 equal signs
6   print 1 | 4,"\n";       # 001 & 100
7   print 5 | 0,"\n";       # 101 | 000
8   print 4 | 0,"\n";       # 100 | 000
9   print 0 | 4,"\n";       # 000 | 100
    print "=" x 10,"\n";    # print 10 equal signs
10  print 5 ^ 4,"\n";       # 101 ^ 100
11  print 5 ^ 0,"\n";       # 101 ^ 000
12  print 4 ^ 0,"\n";       # 100 ^ 000
13  print 0 ^ 4,"\n";       # 000 ^ 100

(Output)
1   4
2   0
3   0
4   0
5   ==========
6   5
7   5
8   4
9   4
    ==========
10  1
11  5
12  4
13  4

					  

Explanation

  1. 5 bitwise anded to 4 results in 000 binary, 4 decimal.

  2. 5 bitwise anded to 0 results in 000 binary, 0 decimal.

  3. 4 bitwise anded to 0 results in 000 binary, 0 decimal.

  4. 0 bitwise anded to 4 results in 000 binary, 0 decimal.

  5. The x operator tells the print function to print 10 equal signs.

  6. 1 bitwise ored to 4 results in 101 binary, 5 decimal.

  7. 5 bitwise ored to 0 results in 101 binary, 5 decimal.

  8. 4 bitwise ored to 0 results in 100 binary, 4 decimal.

  9. 0 bitwise ored to 4 results in 100 binary, 4 decimal.

  10. 5 bitwise exclusively ored to 4 results in 001 binary, 1 decimal.

  11. 5 bitwise exclusively ored to 0 results in 101 binary, 5 decimal.

  12. 4 bitwise exclusively ored to 0 results in 100 binary, 4 decimal.

  13. 0 bitwise exclusively ored to 4 results in 100 binary, 4 decimal.

Example 6.15.

(The Script)
    #!/usr/bin/perl
    # Convert a number to binary
1   while (1) {
2       $mask = 0x80000000;      # 32-bit machine
3       printf("Enter an unsigned integer: ");
4       chomp($num=<STDIN>);
5       printf("Binary of %x hex is: ", $num);
6       for ($j = 0; $j < 32; $j++) {
7          $bit = ($mask & $num) ? 1 : 0;
8          printf("%d", $bit);
9          if ($j == 15)){
10             printf("--");
           }
11     $mask /=2;              # $mask >>= 1; not portable
       }
       printf("\n");
    }
(Output)
Enter an unsigned integer: 1
Binary of 1 hex is: 0000000000000000--0000000000000001
Enter an unsigned integer: 5
Binary of 5 hex is: 0000000000000000--0000000000000101
Enter an unsigned integer: 10
Binary of a hex is: 0000000000000000--0000000000001010
Enter an unsigned integer: 12
Binary of c hex is: 0000000000000000--0000000000001100
Enter an unsigned integer: 15
Binary of f hex is: 0000000000000000--0000000000001111
Enter an unsigned integer: 200
Binary of c8 hex is: 0000000000000000--0000000011001000

					  

Explanation

  1. This little program introduces some constructs that have not yet been discussed. It is presented here as an example of using bitwise operations to perform a real task (in this case, to convert a number to binary and print it). The first line starts a loop that will continue until the user presses <Ctrl>-c (UNIX) or <Ctrl>-z (Windows).

  2. The scalar is set to the hexadecimal value representing 32 zeros. This program works on a machine with a 32-bit word.

  3. The user is asked to type in an integer.

  4. The number is assigned and the newline is chomped.

  5. The printf will print the value of the number in hexadecimal notation.

  6. The for loop will iterate 32 times, once for each bit.

  7. The value of $mask is bitwise anded to $num. If the result is 1, 1 will be assigned to $bit; otherwise, 0 is assigned. (See "Conditional Operators.")

  8. The value of $bit is printed.

  9. If the value of $j is 15 (the loop has iterated 16 times), a double underscore is printed.

  10. The value of $mask is divided by 2. This has the same effect as shifting the bits to the right once but will not try to shift the sign bit if one exists.

6.3.9. Conditional Operators

The conditional operator is another taken from the C language. It requires three operands and thus it is often called a ternary operator. It is used as a shortcut for the if/else construct.

Format

conditional expression ? expression : expression

Example 6.16.

$x ? $y : $z

Explanation

If $x is true, $y becomes the value of the expression. If $x is false, $z becomes the value of the expression.


Example 6.17.

(The Script)
    print "What is your age? ";
2   chomp($age=<STDIN>);

3   $price=($age > 60 ) ? 0 : 5.55;
4   printf "You will pay \$%.2f.\n", $price;

(Output)
1   What is your age? 44
4   You will pay $5.55.

(Output)
1   What is your age? 77
4   You will pay $0.00.

Explanation

  1. The string What is your age? is printed to STDOUT.

  2. The input is read from the terminal and stored in the scalar $age. The newline is chomped.

  3. The scalar $price is assigned the result of the conditional operator. If the age is greater than 60, the price is assigned the value to the right of the question mark (?). Otherwise, the value after the colon (:) is assigned to the scalar $price.

  4. The printf function prints the formatted string to STDOUT.

Example 6.18.

(The Script)
1   print "What was your grade? ";
2   $grade = <STDIN>;
3   print $grade > 60 ? "Passed.\n" : "Failed.\n";

(Output)
1   What was your grade? 76
3   Passed.
(Output)
1   What was your grade? 34
3   Failed.

Explanation

  1. The user is asked for input.

  2. The input is assigned to the scalar $grade.

  3. The print function takes as its argument the result of the conditional expression. If the grade is greater than 60, Passed. is printed; otherwise, Failed. is printed.

6.3.10. Range Operator

The range operator is used in both scalar and array context. In a scalar context, the value returned is a Boolean, 1 or 0. In an array context, it returns a list of items starting on the left side of the operator and counting by ones until the value on the right-hand side is reached.

Example 6.19.

1   print 0 .. 10,"\n";
    0 1 2 3 4 5 6 7 8 9 10

2   @alpha=('A' .. 'Z');
print  "@alpha";'
    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

3   @a=('a'..'z', 'A'..'Z');
print  "@a\n";'
    a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H
I J K L M N O P Q R S T U V W X Y Z

4   @n=( -5 .. 20 );
print "@n\n";'
    -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Explanation

  1. Print the numbers 0 to 10.

  2. Create an array called @alpha and store all uppercase letters in the array in the range from A to Z. The context is array. Print the array.

  3. Create an array called @alpha and store all lowercase letters in one list and all uppercase letters in another list. Print the array.

  4. Create an array called @n and store all numbers in the range between -5 and 20. Print the array.

6.3.11. Special String Operators and Functions

A number of operations can be performed on strings. For example, the concatenation operator joins two strings together, and the string repetition operator concatenates as many copies of its operand as specified.

Perl also supports some special functions for manipulating strings (see Table 6.14). The substr function returns a substring found within an original string, starting at a byte offset in the original string and ending with the number of character positions to the right of that offset. The index function returns the byte offset of the first character of a substring found within the original string. The length function returns the number of characters in a given expression.

Table 6.14. String Operations
ExampleMeaning
$str1 . $str2Concatenate strings $str1 and $str2
$str1 x $numRepeat $str1, $num times
substr($str1, $offset, $len)Substring of $str1 at $offset for $len bytes
index($str1, $str2)Byte offset of string $str2 in string $str1
length(EXPR)Returns the length in characters of expression, EXPR
rindex($str, $substr, POSITION)Returns the position of the last occurrence of $substr in $str.

If POSITION is specified, start looking there.

If POSITION is not specified, start at the end of the string.
chr(NUMBER)Returns the character represented by that NUMBER in the ASCII character set. For example, chr(65) is the letter A.
lc($str)Returns a lowercase string
uc($str)Returns an uppercase string


Example 6.20.

(The Script)
    #!/usr/bin/perl
1   $x="pop";
2   $y="corn";
3   $z="*";
4   print $z x 10, "\n";              # Print 10 stars
5   print $x . $y, "\n";              # Concatenate "pop" and "corn"
6   print $z x 10, "\n";              # Print 10 stars
7   print (($x . $y ."  ")  x  5 );   # Concatenate "pop" and "corn"
                                      # and print 5 times
8   print "\n";
9   print uc($x . $y), "!\n";         # Convert string to uppercase

(Output)
4   **********
5   popcorn
6   **********
7   popcorn popcorn popcorn popcorn popcorn
9   POPCORN!

Explanation

  1. The scalar $x is assigned pop.

  2. The scalar $y is assigned corn.

  3. The scalar $z is assigned *.

  4. The string * is concatenated 10 times and printed to STDOUT.

  5. The value of $x, string pop, and the value of $y, string corn, are concatenated and printed to STDOUT.

  6. The value of $x, string *, is concatenated 10 times and printed to STDOUT.

  7. The strings pop and corn are concatenated five times and printed to STDOUT.

  8. Print a newline to STDOUT.

  9. The uc function converts and returns the string in uppercase. The lc function will convert a string to lowercase.

Example 6.21.

(The Script)
1   $line="Happy New Year";
2   print substr($line, 6, 3),"\n";      # Offset starts at zero
3   print index($line, "Year"),"\n";
4   print substr($line, index($line, "Year")),"\n";
5   substr($line, 0, 0)="Fred, ";
6   print $line,"\n";
7   substr($line, 0, 1)="Ethel";
8   print $line,"\n";
9   substr($line, -1, 1)="r to you!";
10  print $line,"\n";
11  $string="I'll eat a tomato tomorrow.\n";
12  print rindex($string, tom), "\n";
(Output)
2   New
3   10
4   Year
6   Fred, Happy New Year
8   Ethelred, Happy New Year
9   Ethelred, Happy New Year to you!
12  18

Explanation

  1. The scalar $line is assigned Happy New Year.

  2. The substring New of the original string Happy New Year is printed to STDOUT. The offset starts at byte 0. The beginning of the substring is position 6, the N, and the end of the substring is three characters to the right of N. The substring New is returned.

  3. The index function returns the first position in the string where the substring is found. The substring Year starts at position 10. Remember, the byte offset starts at 0.

  4. The substr and index functions are used together. The index function returns the starting position of the substring Year. The substr function uses the return value from the index function as the starting position for the substring. The substring returned is Year.

  5. The substring Fred is inserted at starting position, byte 0, and over length 0 of the scalar $line; i.e., at the beginning of the string.

  6. The new value of $line is printed to STDOUT.

  7. The substring Ethel is inserted at starting position, byte 0, and over length 1 of the scalar $line.

  8. The new value of $line, Ethelred, Happy New Year is printed to STDOUT.

  9. The substring, r to you! is appended to the scalar $line starting at the end (-1) of the substring, over one character.

  10. The new value of $line, Ethelred, Happy New Year to you! is printed to STDOUT.

  11. The $string scalar is assigned.

  12. The rindex function finds the index of the rightmost substring, tom, and returns the index position where it found the substring. That position, 18, is the number of characters starting at the zero-ith position from the beginning of the string to the substring tom in tomorrow.

6.3.12. Arithmetic Functions

In addition to arithmetic operators, Perl provides a number of built-in functions to evaluate arithmetic expressions. (See Table 6.15.)

Table 6.15. Built-in Perl Arithmetic Functions
atan2(Y,X)Returns the arctangent of Y/X in the range –PI to PI.
cos(EXPR) cos EXPRReturns the cosine of EXPR (expressed in radians). If EXPR is omitted, takes cosine of $_.
exp(EXPR) exp EXPRReturns e to the power of EXPR. If EXPR is omitted, gives exp($_).
int(EXPR) int EXPRReturns the integer portion of EXPR. If EXPR is omitted, uses $_.
log(EXPR) log EXPRReturns logarithm (base e) of EXPR. If EXPR is omitted, returns log of $_.
rand(EXPR)

rand EXPR

rand
Returns a random fractional number between 0 and the value of EXPR. (EXPR should be positive.) If EXPR is omitted, returns a value between 0 and 1. See also srand().
sin(EXPR) sin EXPRReturns the sine of EXPR (expressed in radians). If EXPR is omitted, returns sine of $_.
sqrt(EXPR) sqrt EXPRReturn the square root of EXPR. If EXPR is omitted, returns square root of $_.
srand(EXPR) srand EXPRSets the random number seed for the rand operator. If EXPR is omitted, does srand(time).


There are also a number of less-used general utility functions provided by CPAN in a module called List::Util, including first(), max(), maxstr(), min(), minstr(), reduce(), shuffle(), and sum. See: http://perldoc.perl.org/List/Util.html#DESCRIPTION.

Generating Random Numbers

When looking for a good description of random number generation on the Web, one of the related categories is Games>Gambling>Lotteries>Ticket Generators. Games and lotteries depend on the use of random number generation and so do more sophisticated programs, such as cryptographic protocols that use unpredictable encrypted keys to ensure security when passing information back and forth on the Web.

Random numbers produced by programs are called pseudorandom numbers. As described in an article by Ian Goldberg and David Wagner concerning Web security, truly random numbers can be found only in nature, such as the rate of decay of a radioactive element. Apart from using external sources, computers must generate these numbers themselves, but since computers are deterministic, these numbers will not be truly random.[4] Perl programs that need to generate pseudorandom numbers can use the built-in rand function described next.

[4] Goldberg, I., and Wagner, D., "Randomness and the Netscape Browser. How Secure is the World Wide Web?" Dr. Dobb's Journal, http://www.ddj.com/articles/1996/9601h/9601h.html.

The rand/srand Functions

The rand function returns a pseudorandom fractional number between 0 and 1. If EXPR has a positive value, rand returns a fractional number between 0 and EXPR. The srand function sets the random number seed for the rand function but is no longer required if you are using a version of Perl greater than 5.004. A seed is a random number itself that is fed to the random number generator as the starting number from which new random numbers are produced. The rand function is given a seed and, using a complex algorithm, produces random numbers within some range. If the same seed is fed to the rand function, the same series of numbers will be produced. A different seed will produce a different series of random numbers. The default seed value used to be the time of day, but now a more unpredictable number is selected for you by Perl.

Format

rand(EXPR)
rand EXPR
rand

srand(EXPR)
srand EXPR

Example 6.22.

(The Script)
    #!/usr/bin/perl
1   $num=10;
2   srand(time|$$); # Seed rand with the time or'ed to
                    # the pid of this process
3   while($num){    # srand not necessary in versions 5.004 and above
4       $lotto = int(rand(10)) + 1;
                    # Returns a random number between 1 and 10
5       print "The random number is $lotto\n";
        sleep 3;
        $num--;
    }

(Output)
5   The random number is 5
    The random number is 5
    The random number is 7
    The random number is 8
    The random number is 1
    The random number is 5
    The random number is 4
    The random number is 4
    The random number is 4
    The random number is 6

					  

Explanation

  1. The value of $num will be used in the while loop on line 7, which will iterate 10 times.

  2. The srand function sets the seed for the rand function to a unique starting point, the return value of the built-in time function bitwise ored to the process identification number of this Perl program ($$).

  3. The while loop will iterate 10 times.

  4. The rand function will return an integer value between 1 and 10, inclusive. The value will be assigned to $lotto.

  5. The value of the random number is printed.


 

Example 6.23.

(The Script)
    #!/usr/bin/perl
1   $x=5 ;    # Starting point in a range of numbers
2   $y=15;    # Ending point

    # Formula to produce random numbers between 5 and 15 inclusive
    # $random = int(rand($y - $x + 1)) + $x;
    # $random = int(rand(15 - 5 + 1)) + 5

3   while(1){
4       print int(rand($y - $x + 1)) + $x , "\n";
5       sleep 1;
    }

(Output)
15
14
5
10
11
6
12
6
7
10
6
8
6
15
11

					  

Explanation

  1. The scalar $x is assigned the starting value in the range of numbers produced by the rand function.

  2. The scalar $y is assigned the ending value of the range of numbers produced by the rand function.

  3. An infinite while loop is started. To exit, the user must type <Ctrl>-d (UNIX) or <Ctrl>-z (Windows).

  4. The rand function is given a formula that will produce random integer values in the range 1 to 15, inclusive.

  5. The sleep function causes the program to pause for 1 second.

Previous Page Next Page