Numbers
Designating numbers
In computer languages, numbers are generally categorized into two groups: integers and floating point numbers. An integer has no decimal point or fractional part, whereas a floating point number does. For most programming languages, these are stored differently in memory. Perl version 5.8 also makes this distinction.
What we do have to worry about is providing numbers to Perl in the correct format. In general, numbers are formatted in Perl just as you would write them out naturally:
$x = 45; # an integer $y = 57.234; # a floating point number $pi = 3.14159265358979; # another floating point number $z = -30; # a negative integer
If you want to use a number such as Avogadro’s number (6.02 x 1023),
then you have to convert it to the format that Perl recognizes, 6.02e23
or 6.02E23, where the e or E indicates the power
of 10 that is used. Negative powers are allowed (e.g., 1.465e-4 for
1.465 x 10-4). Perl does not recognize a number such as e-40;
this has to be written as 1e-40.
If you have a long integer, such as 288,456,349, you can’t put the commas into
the number in Perl. Instead, you can replace the commas with underscores, like
this: 288_456_349.
$avogadro = 6.02e23; $pValue = 1.47e-48; $longInt = 288_456_359; $longFrac = 0.004_452_123
For hard-core computer types coming from low-level languages such as C, there are formats for expressing integers in binary (base 2), octal (base 8), and hexadecimal (base 16) format. See the references below for more information on these.
References:
- Learning Perl (3rd ed.), pp. 20-21.
- Programming Perl (3rd ed.), pp. 59-60.
Math operators
Adding with the + operator
Numbers and the values of variables are added using the + operator:
$x = 4.23 + 5.27; # $x contains 9.50 $x = $x + 2.22; # $x now contains 11.72 $y = 5.67; $z = $x + $y; # $z contains 17.39 $i = 4; $i = $i + 1; # increment $i
As shown on line 2 above, you can add something to a variable and put the result
back into the variable. There is a more efficient way to write this, using the += operator.
Incrementing a variable means to increase its value by 1, as shown in line 6 above.
Incrementing a variable containing an integer is common in loops. There is a more
efficient way to write this, using the ++
operator.
Subtracting with the - operator
Numbers and the values of variables are subtracted using the -
operator:
$x = 4.23 - 5.27; # $x contains -1.04
$x = $x - 2.22; # $x now contains -3.26
$y = -5.67; # not subtraction, but initialization with a
# negative number
$z = $x - $y; # $z contains -8.93
$i = 4;
$i = $i - 1; # decrement $i
As shown on line 2 above, you can subtract something from a variable and put the
result back into the variable. There is a more efficient way to write this, using the -= operator.
Decrementing a variable means to reduce its value by 1, as shown in line 6 above.
Decrementing a variable containing an integer is common in loops. There is a more
efficient way to write this, using the --
operator.
Multiplying with the * operator
Numbers and the values of variables are multiplied using the *
operator:
$x = 4 * 5 # $x contains 20.0 $x = $x * 0.5 # $x now contains 10.0 $y = -3; # initialization with a negative number $z = $x * $y; # $z contains -30.0
As shown on line 2 above, you can multiply a variable by something and put the
result back into the variable. There is a more efficient way to write this, using the *= operator.
If multiplication and addition or subtraction occur in an expression without parentheses, multiplication happens before addition or subtraction. Operations in parentheses occur first, so use parentheses to make things happen the way you want them to.
$x = 2 + 3 * 5; # $x contains 2 + 15 = 17 $x = ( 2 + 3 ) * 5; # $x contains 5 * 5 = 25
Dividing with the / operator
Numbers and the values of variables are divided using the / operator:
$x = -20 / 4; # $x contains -5.0 $x = 1 / 7; # $x contains 0.142857142857 $x = $x / 2; # $x now contains 0.0714285714286
As shown on line 3 above, you can multiply a variable by something and put the
result back into the variable. There is a more efficient way to write this, using the /= operator.
If division and addition or subtraction occur in an expression without parentheses, division happens before addition or subtraction. Operations in parentheses occur first, so use parentheses to make things happen the way you want them to.
$x = 6 + 15 / 3; # $x contains 6 + ( 15 / 3 ) = 11 $x = ( 6 + 15 ) / 3; # $x contains 21 / 3 = 7 $x = 6 + 15 / 3 + 4; # $x contains 6 + ( 15 / 3 ) + 4 = 15 $x = ( 6 + 15 ) / ( 3 + 4 ) # $x contains 21 / 7 = 3
If multiplication and division occur in an expression without parentheses, the operators are left-associative, meaning things on the left happen first. Operations in parentheses occur first, so use parentheses to make things happen the way you want them to.
$x = 2 * 3 / 6; # $x contains ( 2 * 3 ) / 6 = 1 $x = 2 * ( 3 / 6 ); # $x contains 2 * 0.5 = 1 $x = 8 / 2 / 2; # $x contains ( 8 / 2 ) / 2 = 2 $x = 8 / ( 2 / 2 ); # $x contains 8 / 1 = 8
Finding the remainder with the % (modulo) operator
The % (modulo or modulus) operator converts two numbers to integers,
divides the first by the second, and returns the remainder. Customarily, this is
used only on integer values.
$x = 10 % 3 # $x contains 1
Calculating a power with the ** (exponentiation) operator
When you want to find the power of a number, use the ** operator.
$x = 2 ** 3; # $x contains 8 $x = 2 ** 0.5; # one way to find a square root; $x = 1.414...
Combining math operators with the = (assignment) operator
In the examples above, we have changed the value of a variable and assigned the result back to the variable, like this:
$x = $x + 5; $x = $x - 4; $x = $x * 3; $x = $x / 2; $x = $x % 2; $x = $x ** 2;
This sort of thing is so common that Perl provides a shorter way to write these:
$x += 5; # $x = $x + 5; $x -= 4; # $x = $x - 4; $x *= 3; # $x = $x * 3; $x /= 2; # $x = $x / 2; $x %= 2; # $x = $x % 2; $x **= 2; # $x = $x ** 2;
Incrementing and decrementing
We often use a variable in a loop as a counter to keep track of the number of times we’ve gone through the loop. Each time through the loop, we will either increment the counter (increase its value by 1) or decrement the counter (decrease its value by 1). We have seen two ways to do this:
$x = $x + 1; # increment $x $x += 1; # increment $x $y = $y - 1; # decrement $y $y -= 1; # decrement $y
Here are two ways to write a loop that prints "I do not like
Draco Malfoy.\n" three times:
# loop with increment (counting up)
$i = 0;
while ( $i < 3 )
{
print( "I do not like Draco Malfoy.\n" );
$i += 1;
}
# loop with decrement (counting down)
$i = 3;
while ( $i > 0 )
{
print( "I do not like Draco Malfoy.\n" );
$i -= 1;
}
Since incrementing and decrementing a variable are so common, Perl provides third, shorter ways to write these operations:
++$x; # increment $x $x++; # increment $x --$x; # decrement $x $x--; # decrement $x
We can change our loop examples as follows:
# loop with increment (counting up)
$i = 0;
while ( $i < 3 )
{
print( "I do not like Draco Malfoy.\n" );
$i++;
}
# loop with decrement (counting down)
$i = 3;
while ( $i > 0 )
{
print( "I do not like Draco Malfoy.\n" );
$i--;
}
There is a difference between putting the ++ or -- before
or after the name of the variable. Put these operators before the variable
if you want to increment or decrement the variable before using the
variable. Put these operators after the variable if you want to increment
or decrement the variable after using it.
Here are two simple loops that show the difference. In the first loop, we increment the variable after using it:
# loop with increment (counting up)
# increment the variable after using it
$i = 0;
while ( $i < 5 )
{
print( $i++, "\n" );
}
The output from this loop is:
0 1 2 3 4
In the second loop, we increment the variable before using it:
# loop with increment (counting up)
# increment the variable before using it
$i = 0;
while ( $i < 5 )
{
print( ++$i, "\n" );
}
The output from this loop is:
1 2 3 4 5
References:
- Learning Perl (3rd ed.), p. 22.
- Programming Perl (3rd ed.), pp. 86-110.
Math functions
Finding the square root of a number
Square roots of a number can be determined either by using the sqrt()
function or by exponentiating the number to the 0.5 power. You have to use the
exponentation operator to find any other root such as a cube root.
$x = 2; $y = sqrt( $x ); # Calculate the square root of 2. $y = $x ** 0.5; # Calculate the square root of 2. $z = sqrt( 45 ); # Calculate the square root of 45. $r = 64 ** ( 1 / 3 ); # Calculate the cube root of 64.
Finding the natural logarithm of a number
Use the log() function to find the natural logarithm of a number. If
you want the base 10 logarithm, then calculate the natural logarithm of the number
and divide that by the natural logarithm of 10.
$x = log( 20 ); # Find the natural logarithm of 20. $x = log( 20 ) / log( 10 ); # Find the logarithm of 20 to base 10.
Getting a random number
Use the rand() function to get a random number between
0 and 1, including 0 but excluding 1. Give the rand() function
an argument to change the range; rand( 10 ) returns a random
number between 0 and 10, including 0 but excluding 10.
$x = rand(); # Get a random number between 0 and 1. $y = rand( 4.0 ); # Get a random number between 0 and 4.
Strings
A string is simply a sequence of characters of any length, such as
"" (a zero-length string), "a" (a string one
character in length), or "Hermione Granger’s parents are muggles.".
Strings in quotation marks are called string literals. It makes a difference whether you put a string in single or double quotes.
Double quote strings
Double quote strings are bounded by double quote characters. These are the most
common string literals. Use a double quote string when you want to include a
special character such as a tab ("\t") or a newline
("\n"), or when you want the value of a variable to appear in
the string ("Welcome, $user."). The code:
$user = "Hermione"; print( "Welcome, $user.\n" );
produces:
Welcome, Hermione.
If you want to print the name of the variable in a double-quoted string, then you have to put a backslash in front of its name. The code:
$user = "Hagrid"; print( "\$user contains $user.\n" );
produces:
$user contains Hagrid.
If you want to include double quote characters in a double quote string, then you have to a backslash in front of each double quote character that you want to include. The code:
print( "Ron asked, \"Why?\"\n" );
produces:
Ron asked, "Why?"
Single quote characters in a double quote string are not a problem and don’t require a backslash in front of them. The code:
print( "Harry answered, 'Because.'\n" );
produces:
Harry answered, 'Because.'
Finally, if you want a backslash to appear in your output, then you have to put a backslash in front of the backslash. The code:
print( "This is a backslash: \\.\n" );
produces:
This is a backslash: \.
Single quote strings
Single quote strings are bounded by single quote charcters. Use single quote strings when you want the string to appear exactly as entered. Special characters and variables are not converted. Double quote characters are not a problem in single quote strings, but if you want to use single quote characters, you have to put a backslash in front of each one. And to put a backslash in a single quote string, put a backslash in front of it.
This code:
$user = "Roger"; print( 'Welcome, $user, to \'Who wants to be a "Perl" programmer?\'\n' );
produces:
Welcome, $user, to 'Who wants to be a "Perl" programmer?'\n
Note that the variable, $user, was not replaced with its value, and
that the new line string, \n, was not converted to a new line
character.
References:
- Learning Perl (3rd ed.), pp. 22-24.
- Programming Perl (3rd ed.), pp. 60-65.
Concatenating strings with the . operator
Two strings can be concatenated using the . operator. If you want to
append a string to a variable, you can use the .= operator.
$x = "Mr. and Mrs. Dursley, of number four, " . "Privet Drive, were "; $x .= "proud to say that they were perfectly normal, "; $y = "thank you very much."; $x .= $y;
When all the concatenations are complete, the variable $x contains
the string "Mr. and Mrs. Dursley, of number four, Privet Drive, were
proud to say that they were perfectly normal, thank you very much.".
(This is the first sentence of Harry Potter and the Sorcerer’s Stone,
by J. K. Rowling.)
References:
- Learning Perl (3rd ed.), p. 29.
- Programming Perl (3rd ed.), p. 95.
Getting a substring with the substr() function
You can pull a part of a string out a string using the substr()
function. This function takes three arguments. The first argument is a string
literal or a variable that contains a string. The second argument is the character
position from which you want to obtain the substring. (The first character is at
position 0.) The third argument is the number of characters you want in the
substring.
This function is handiest when you have a data file with fixed-width columns, where you know the character position of each column of data.
Here is an example:
# Initialize a fixed-width data line with first name in character columns # 0-11, last name in character columns 12-23, and the Hogwarts house in # columns 24-35. $data = "Harry Potter Gryffindor "; # Extract the fields. $firstName = substr( $data, 0, 12 ); # contains "Harry " $lastName = substr( $data, 12, 12 ); # contains "Potter " $house = substr( $data, 24, 12 ); # contains "Gryffindor " # Print the extracted fields to display their contents. print( "'$firstName'\n" ); print( "'$lastName'\n" ); print( "'$house'\n" );
The output from this code fragment is:
'Harry ' 'Potter ' 'Gryffindor '
References:
- Learning Perl (3rd ed.), pp. 209-211.
- Programming Perl (3rd ed.), pp. 805-806.
Printing formatted numbers and strings
You can format numbers and strings using the printf() and
the sprintf() functions. There are many formats, given in
Programming Perl, 3rd Edition, pp. 797-799. We’ll concentrate
on four of these.
Using printf()
The printf() function prints to a filehandle (such as STDOUT,
STDERR, or a file handle corresponding to a file you have opened).
printf() takes as an argument a formatting
string that contains fields for formatting numbers and strings. You indicate
the position of each formatted field within the formatting string with the % symbol followed
by a letter. Succeeding arguments of the printf() function are the values that you want to print
in the fields.
Formatting integers with %d
A %d field indicates that you want to print an
integer at that position.
$x = 4; printf( STDOUT "The integer is %d.\n", $x ); printf( STDOUT "%d squared equals %d.\n", $x, $x ** 2 );
The output from this code fragment is:
The integer is 4. 4 squared equals 16.
Formatting floating point numbers with %f
A %f field indicates that you want to print a floating point
number at that position. You can indicate how many digits you want after
the decimal by putting a decimal point and the number of digits you desire
in front of the f. For example, %.4f indicates that you want
to print a floating point number with 4 digits of precision.
$x = 4; printf( STDOUT "%f squared equals %f.\n", $x, $x ** 2 ); printf( STDOUT "%.4f squared equals %.4f.\n", $x, $x ** 2 );
The output from this code fragment is:
4.000000 squared equals 16.000000. 4.0000 squared equals 16.0000.
Formatting strings with %s
The %s field indicates that you want to format a string at
that position in the string.
# Example of printing strings. $name = 'Dumbledore'; $occupation = 'headmaster'; printf( STDOUT "%s's occupation is %s.\n", $name, $occupation );
The output from this code fragment is:
Dumbledore's occupation is headmaster.
Formatting percent symbols with %%
Finally, the %% field indicates that you just want to print
a percent symbol at that position in the string.
$successes = 30; $total = 50; printf( "The success rate was %.2f%%.\n", 100 * $successes / $total );
The output from this code fragment is:
The success rate was 60.00%.
Using sprintf()
Use the sprintf() function when you want to format a string
but you’re not ready to send it to a filehandle yet. sprintf()
returns the formatted string, which you can save in a variable for later use.
# Example of printing an integer and a floating point number, with
# four places after the decimal for the floating point number.
$x = 5;
$formattedString =
sprintf( "The square root of %d is %.4f\n", $x, sqrt( $x ) );
print( STDOUT $formattedString );
The output from this code fragment is:
The square root of 5 is 2.2361
References:
- Programming Perl (3rd ed.), pp. 797-799.
Homework assignment
Write a script that creates a file containing the following calculations on the integers 1 through 10:
- the number itself
- the reciprocal of the number
- the square root of the number
- the natural logarithm of the number
- the number squared
The output should look something like this:
n 1/n sqrt(n) log(n) n**2 1 1.0000 1.0000 0.0000 1.0000 2 0.5000 1.4142 0.6931 4.0000 ... 10 0.1000 3.1623 2.3026 100.0000
As you work on this script or any other script, write a few lines of code, then test the script. Don’t try to write the entire script at once. Analyze the problem and try to break it into small parts. Then add each part one at a time.
Here are the individual parts of the script:
- Open a file to which you’ll write the output.
- Print a header line with labels for the columns.
-
Start a loop using
whilein which you increment a variable from 1 to 10. - Calculate the reciprocal of the number, the square root of the number, the natural log of the number, and the number squared, and save these values in variables.
-
Print the calculated numbers to the output file using
printf(),%d, and%fto format the numbers. Fix the output so that all floating point values have 4 digits after the decimal point. Separate all columns with two or more space characters. Make sure all the decimal points line up.
Here are the steps I would use to write the script.
-
Write a script that opens a file for writing, writes the column names, then closes
the file. Use the
open()function and make sure to put<>in front of the file name to indicate that you want to write to the file. Use theprint()function to print the column names to the file. Use theclose()function to close the file. -
When you have completed step 1 successfully, then add a
whileloop that increments a variable from 1 to 10. Print the value of the variable to the output file each time through the loop. -
When you have completed step 2 successfully, then calculate the reciprocal of the
number (
1/$n), the square root of the number (sqrt( $n )), the natural logarithm of the number (log( $n )), and the number squared (n**2), and save these values to variables. Use theprint()function to print the values of these variables to the output file so you can check that the calculations are correct. -
When you have completed step 3 successfully, then substitute
printf()forprint()and use%dand%fto format the output correctly.