A Balanced Introduction to Computer Science and Programming

David Reed
Creighton University

Copyright © 2004 by Prentice Hall



Chapter 5: Data Types and Expressions


In Chapter 4, you began using JavaScript to store values and display messages in Web pages. While all of the examples in the chapter were text based, JavaScript allows for computation involving numbers and Boolean (true/false) values as well. In this chapter, you will study the basic data types of JavaScript and the operations defined for those types. You will also familiarize yourself with some of JavaScript's predefined functions, including common mathematical functions.


Data Types and Operators

So far, you have used the JavaScript write statement to display messages. Such messages, text enclosed in quotes, are known as strings. In addition to strings, data values in JavaScript can also be numbers and Booleans (true/false values that will be explored in Chapter 11). Each of the data types in JavaScript has operators predefined for manipulating values of that type. For example, you have already seen that strings can be concatenated, i.e., joined end-to-end, using '+'. Not surprisingly, the standard arithmetic operators '+' (addition), '-' (subtraction), '*' (multiplication), and '/' (division) are also predefined for numbers.

JavaScript variables can be assigned values of any type, including numbers and mathematical expressions formed by applying operators to numbers. When an expression appears on the right-hand side of an assignment, that expressions must be evaluated first, then the resulting value is assigned to the variable on the left-hand side. For example, the first assignment below stores the value 24 in the memory cell corresponding to variable x. In the second assignment, the expression on the right-hand side evaluates to 1024, and so 1024 is assigned to y's memory cell, leaving x unchanged. In the third assignment, the expression on the right-hand side evaluates to 1023 (based on the current value of y), and so 1023 is assigned to x's memory cell, overwriting the previous contents.

x = 24;      
  24 
x
  
y = (100 * 10) + 24;      
  24 
x
  
1024
y
x = y - 1;      
1023
x
  
1024
y

Similarly, JavaScript write statements can be used to display values of any type, including numbers and numeric expressions. For example,

document.write("The sum of 3 and 7 is " + (3 + 7) + ".<br />"); would produce the output:   The sum of 3 and 7 is 10.   and x = 18; document.write("Twice " + x + " is " + (2*x) + ".<br />"); would produce the output:   Twice 18 is 36.


EXERCISE 5.1:   Trace the execution of the following JavaScript code and try to predict its behavior. For each assignment, fill in the boxes corresponding to the values of the variables -- even those values that aren't changed. For each write statement, list the output that would be displayed.

num1 = 14;      
        
num1
  
num2 = 8 - (3 + 2);      
        
num1
  
        
num2
document.write("num1 = " + num1 + ", num2 = " + num2 + "<br />");


num3 = 99;      
        
num1
  
        
num2
  
        
num3
num1 = 99 / 2;      
        
num1
  
        
num2
  
        
num3
num2 = 2 * num1;      
        
num1
  
        
num2
  
        
num3
num3 = num2 - (num1 + 45.5);      
        
num1
  
        
num2
  
        
num3
document.write("num1 = " + num1 + 
               ", num2 = " + num2 + ", num3 = " + num3 + "<br />");


num2 = num3 + num1;      
        
num1
  
        
num2
  
        
num3
document.write("num2 = " + num2 + "<br />");


Verify your predictions by cut-and-pasting the above code into a Web page (within SCRIPT tags) and loading that page in the browser. You do not need to save or print this page.


In mathematics, where the symbol '=' is used for equality, a statement such as the   x = x + 1;   wouldn't make much sense. In JavaScript, however, you must keep reminding yourself that '=' is used for assigning values to variables, not for testing equality. As in any assignment, the expression on the right-hand side of an assignment is evaluated first using the current values of variables. Then, the value of that expression is assigned to the variable on the left-hand side of the assignment. In this example, the result is that the current value of x is incremented by one, and the result is assigned back to x.


Common errors to avoid...

To avoid confusion, try to refrain from using the word "equals" when referring to the '=' operator. Instead, say "gets" to emphasize the fact that an assignment statement gives the variable on the left-hand side a value. Thus, the assignment "x = x + 1;" should be read as "x gets x + 1;". Not only will this reading reinforce the correct intuition, but it will also avoid confusion later when the equality operator '==' is introduced.



EXERCISE 5.2:   Trace the execution of the following JavaScript code and try to predict its behavior. For each assignment, fill in the boxes corresponding to the values of the variables -- even those values that aren't changed. For each write statement, list the output that would be displayed.

q = 0;      
        
q
  
q = q + 1;      
        
q
document.write("q = " + q + "<br />");


q = q + 1;      
        
q
t = q * q;      
        
q
  
        
t
document.write("q = " + q + ", t = " + t + "<br />");


Verify your predictions by cut-and-pasting the above code into a Web page (within SCRIPT tags) and loading that page in the browser. You do not need to save or print this page.


Interesting facts about numbers in JavaScript:


Common errors to avoid...

While the precedence rules of JavaScript are clear to the browser, relying on those rules to evaluate complex expressions as you intended is risky. For example, it is not uncommon for a person to write (x+1 * z), intending for the value of x to be incremented first before the multiplication. To avoid any possible confusion, add parentheses to ensure that sub-expressions are evaluated in the correct order, i.e., ((x+1) * z).



Evaluating Mixed Expressions

In JavaScript, the '+' operator actually serves two purposes. When applied to numeric values, it represents addition as demonstrated above. When applied to string values, the '+' operator represents concatenation. This behavior has been demonstrated repeatedly in write statements, where an output message has been broken into pieces. For example,

document.write("This is a really long message that " + "is broken into pieces across lines."); color = prompt("What is your favorite color?", ""); document.write("I like " + color + " too!");

When the '+' operator is applied to mixed values, a string and a number, the browser automatically converts the number into a string and then concatenates. For example, the steps involved in evaluating a mixed expression are shown below:

"We're number " + 1 ==> "We're number " + "1" ==> "We're number 1"

If proper care is not taken, mixed expressions involving strings and numbers can produce unexpected results. Since expressions involving '+' are evaluated from left to right, the similar expressions below yield substantially different results:

3 + 2 + " is the sum" ==> (3 + 2) + " is the sum" ==> 5 + " is the sum" ==> "5" + " is the sum" ==> "5 is the sum" "the sum is " + 3 + 2 ==> ("the sum is " + 3) + 2 ==> ("the sum is " + "3") + 2 ==> "the sum is 3" + 2 ==> "the sum is 3" + "2" ==> "the sum is 32"


EXERCISE 5.3:   What do each of the following expressions evaluate to? Show the steps involved in each evaluation (as demonstrated in the two examples above). "My favorite number is " + 10 + 24 "My favorite number is " + (10 + 24) "My favorite number is " + 10 + "" + 24

Verify your predictions by displaying the value of each of these expressions in a Web page (using write statements within SCRIPT tags). You do not need to save or print this page.


Common errors to avoid...

Special care must be taken when displaying messages with embedded mathematical expressions. As EXERCISE 5.3 demonstrated, the left-to-right evaluation of write statement messages can lead to concatenation when addition is really the intention. For example, in the following statement:

document.write("<p>Double that number is " + x + x); the intention of the programmer was probably for the value of x to be added to itself. However, the fact that evaluation goes from left to right means that the first x will be concatenated with the string to its left, then the result concatenated with the second x. To avoid unintended errors such as this, always surround mathematical expressions with parentheses when mixing with strings.



When reading in numbers using the prompt function, special care must be taken. The prompt function always returns the user's input in the form of a string, even when they enter a number. For example, the input value 500 would be returned by prompt as "500". Usually, this is not a problem since JavaScript will automatically convert the string to a number when a numeric operation (such as '*' or '-') is applied. However, addition is a problem since the '+' operator may be interpreted as string concatenation. Consider the following sequence of JavaScript statements.

myNumber = prompt("Enter a number", ""); document.write("One more is " + (myNumber + 1));

If the user entered 12 at the prompt, the subsequent write statement would actually display the message "One more is 121". This follows from the fact that the call to prompt will return "12", which is then stored in the variable myNumber and used to evaluate the expression (myNumber + 1) --> ("12" + 1) --> "121". Fortunately, JavaScript provides a predefined function for explicitly converting strings to numeric values. The parseFloat function takes as input a string that represents a number (such as "500") and returns the corresponding number value. For example,

myNumber = prompt("Enter a number", ""); myNumber = parseFloat(myNumber); document.write("One more is " + (myNumber + 1));

Here, the second assignment calls parseFloat to convert the string value "12" into its numeric equivalent 12, and stores that number back in the variable myNumber. As a result, the '+' operator represents addition and the message "One more is 13" is displayed.

Consider the following Web page that prompts the user for a temperature in degrees Fahrenheit and then displays the corresponding temperature in degrees Celsius.


<html> <!-- ftoc.html Dave Reed --> <!-- --> <!-- Converts a temperature from Fahrenheit to Celsius.--> <!-------------------------------------------------------> <head> <title>Fahrenheit to Celsius</title> </head> <body> <script type="text/javascript"> tempInFahr = prompt("Enter the temperature (in Fahrenheit):", "32"); tempInFahr = parseFloat(tempInFahr); tempInCelsius = (5/9) * (tempInFahr - 32); document.write("You entered " + tempInFahr + " degrees Fahrenheit.<br />"); document.write("That's equivalent to " + tempInCelsius + " degrees Celsius."); </script> </body> </html>


After the temperature (in Fahrenheit) has been read in and stored as a number, the temperature is converted to Celsius using the formula: (5/9) * (tempInFahr - 32). The converted temperature is stored in the variable tempInCelsiust, and then write statements display the results (both the original Fahrenheit temperature and the newly converted Celsius temperature).


EXERCISE 5.4:   Cut-and-paste the ftoc.html text into a new Web page and verify that it behaves as described. In particular, use your page to convert each of the following temperatures from Fahrenheit to Celsius, and report the corresponding temperatures. 98.6 Fahrenheit 100 Fahrenheit 212 Fahrenheit 0 Fahrenheit


EXERCISE 5.5:   Similar to your ftoc.html page, define a page named ctof.html that does the opposite conversion. That is, it should prompt the user for a temperature in degrees Celsius and convert that temperature to Fahrenheit using the formula: tempInFahr = ((9/5) * tempInCelsius) + 32; Once you have completed the page, use it to convert the following temperatures: 0 Celsius 20 Celsius -10 Celsius 88 Celsius



EXERCISE 5.6:   Create a Web page named grade.html that can be used to compute your grade for this course. Your page should prompt the user for their lesson average, lab average, discussion average, test average, and final exam score. It should store each of these values in variables as numbers and compute the overall course average. Recall the grade weightings as defined in the course syllabus.

online lessons 25 %
lab assignments 15 %
review questions/discussions 5 %
two 75-minute tests 30 %
100-minute final exam 25 %

Thus, the overall course average can be computed by scaling each individual grade by the appropriate factor and adding (i.e., lessons*0.25 + labs*0.15 + disc*0.05 + tests*0.30 + exam*0.25). Your page should display the grades entered by the student as well as the overall average. For example,

lesson average: 85.5 lab average: 93.0 discussion average: 90 test average: 78.5 final exam score: 88 overall course average: 85.375



Designer secrets...

In Chapter 4, we noticed that pages performing similar tasks had a similar pattern to their code. In particular, the pages considered in Chapter 4 all involved prompting the user for inputs (words or phrases) and then displaying those inputs in messages. As such, the JavaScript code for these pages consisted of a sequence of statements to read and store the inputs (using prompts and assignments to variables) followed by write statements.

The pages above perform more general tasks. They involve reading and storing numbers, performing some computation on those numbers, and then displaying the result. Thus, the pattern to JavaScript code for these types of tasks includes the conversion of inputs values to numbers (using parseFloat) and the additional step(s) of performing the desired computation:

<script type="text/javascript"> number1 = prompt("PROMPT MESSAGE", ""); number1 = parseFloat(number1); number2 = prompt("PROMPT MESSAGE", ""); number2 = parseFloat(number2); . . . numberN = prompt("PROMPT MESSAGE", ""); numberN = parseFloat(numberN); answer = SOME EXPRESSION INVOLVING number1, …, numberN; document.write("MESSAGE INVOLVING answer"); </script>


Predefined JavaScript Functions

In addition to the standard arithmetic operations, JavaScript provides many useful functions for manipulating values. Mathematically speaking, a function is a mapping from some number of inputs to a single output. For example, the "square root" function maps an input number, say 100.0, to its square root, 10.0. Similarly, the "maximum" function maps two inputs, say 4 and 7, to the larger of the two, 7. The JavaScript prompt function that you first encountered in Chapter 4 maps two inputs, a prompt message and a default value, to whatever value is entered by the user. Likewise, the parseFloat function introduced above maps a single input, a string, into its equivalent numeric value.

From a programming point of view, a function may be seen as a unit of computational abstraction. In order to compute the square root of a number, you do not need to know the steps involved in the computation (i.e., the algorithm). You simply apply the predefined square root function and obtain the desired value. With this computational perspective in mind, we will often refer to the application of a function to inputs as calling that function, and the output of the function as its return value. For example,

     The square root function, when called with input 100.0, returns the value 10.0.

     The maximum function, when called with inputs 4 and 7, returns the value 7.

JavaScript provides an extensive library of predefined mathematical functions, including square root (Math.sqrt) and maximum (Math.max). These functions all have names beginning with the prefix "Math.", signifying that they are part of a library of mathematical routines. (Technically speaking, Math is the name of a JavaScript object that contains these functions.)

When calling a function in JavaScript, the function name is written first, followed by the inputs in parentheses. For example, the call Math.sqrt(25) would return the value 5, while Math.max(4, 7) would return 7. The inputs to a function can be any valid JavaScript values, including expressions and variables. Thus, the calls Math.sqrt(3*4 + 13) and Math.max(2+2, 42/6) would similarly return 5 and 7, respectively.

A function call can appear anywhere in a JavaScript expression. When an expression containing a function call is evaluated, the return value for that call is substituted into the expression. For example, in the assignment "x = Math.sqrt(9);", the call on the right-hand side would evaluate to 3, and so the variable x would be assigned the value 3. Similarly, in "x = Math.sqrt(9) + 1;", the expression on the right-hand side adds the function return value 3 to 1, resulting in x being assigned the value 4.


EXERCISE 5.7:    Experiment with each of the following mathematical functions and identify its purpose. Be sure to test a variety of number values for each function, including negative numbers and fractions. Descriptions of the Math.sqrt and Math.max functions are already provided for you. You do not need to save or print the Web page you use for testing these functions.

FUNCTION INPUTS DESCRIPTION



Math.sqrt 1 number    returns the square root of the input
Math.max 2 numbers    returns the greater of the two inputs
Math.min 2 numbers
Math.abs 1 number
Math.floor 1 number
Math.ceil 1 number
Math.round 1 number


Common errors to avoid...

When attempting to call a function, there are two common errors that may occur, and being able to recognize them is extremely useful.

  1. If you mistype the name of a function, then an error will occur and the browser will attempt to identify the error. Using Netscape Navigator, the error message will read "Error: XXX is not a function" or "Error: XXX is not defined", where XXX is the mistyped name. Using Internet Explorer, the error message is more cryptic, "Error: Object Expected". This message refers to the fact that an object with that name was expected (i.e., the function), but its definition could not be found.

  2. Calling a function with the wrong type or number of inputs does not produce an error, but the results may be unexpected. Whenever possible, the browser will automatically convert between numbers and strings in order make inputs match the specified type. Thus, the call Math.sqrt("9") will return 3.0. However, if a number is expected and the specified input is a string that doesn't convert, then the resulting value will be the special symbol, NaN (which stands for "Not a Number"). Any resulting mathematical operations on NaN will likewise yield NaN. Thus, the call Math.sqrt("xyz") will produce NaN, as will Math.sqrt("xyz")+1. If you fail to specify the correct number of inputs to a function, any unspecified inputs will be assigned the special symbol undefined, and any resulting operations on those values will produce either undefined or NaN.


The predefined function Math.pow can be called to raise a number to a power. For example, the call Math.pow(2, 3) will return 23 = 8. The inputs can be any number values, including negative numbers and fractions. For example, Math.pow(2, -1) will return 0.5 while Math.pow(9, 0.5) will return 3.


EXERCISE 5.8:    Recall from Chapter 1 that memory inside the computer is comprised of individual bits of data. A bit (short for binary digit) can store one of only two values, commonly referred to as 0 and 1. However, using two bits, you can represent 4 different values using the bit patterns 00, 01, 10, and 11. With three bits, you can represent 8 different values using 000, 001, 010, 011, 100, 101, 110, and 111. In general, using N bits, you can represent 2N different values.

Create a Web page named bits.html that prompts the user for a number of bits and stores that number in a variable named N. Your page should then compute and display 2N, the number of values that can be represented using that number of bits. For example, if the user entered 10 at the prompt, the page would display:

With 10 bits, you can represent 1024 different values.

Use your page to determine the number of values representable by each of the following:

8 bits (1 byte) 16 bits (2 bytes) 32 bits (4 bytes) 64 bits (8 bytes)

Recall that a function is a mapping from some number of inputs to a single output. Technically, this definition allows for functions with zero inputs, although this may not seem especially useful. To the contrary, there is a predefined function named Math.random that takes no inputs and returns a useful result. Every time Math.random() is called, a different pseudo-random number between 0 (inclusive) and 1 (exclusive) is returned. That is, a number from the range [0...1) is returned, and it can be any number within that range. Technically speaking, the Math.random function uses a complex algorithm to generate numbers that appear random, hence the term "pseudo-random."


EXERCISE 5.9:    Evaluate each of the following expressions 10 times, and report the results. You do not need to save or print the Web page you use for computing these results. Math.random() 2*Math.random() 2*Math.random() + 1 Math.floor(2*Math.random()+1)


Common errors to avoid...

Since the Math.random function does not require any inputs, you may be tempted to leave off the parentheses when calling the function. While this does not cause an error in itself, the resulting behavior is far from the intended call. You may think of a function name as representing a value just like a variable name. Instead of representing a number or string, however, the function name represents a collection of JavaScript statements that define a computation. If you specify the name of a function without parentheses, you are accessing the value associated with that name just as with standard variables. Thus, document.write(Math.random); would actually display the value of the Math.random function, not the result of a call. In this case, the browser would identify the random function as predefined:

function random() { [native code] }



EXERCISE 5.10:    Most lotteries work by selecting a random sequence of balls, each labeled with an integer from some range. For example, Pick-4 lotteries typically utilize four bins, each containing 10 balls labeled 0 through 9. With 10 balls to choose from, there are 104 = 10,000 different number sequences that could be picked. Increasing the number of balls significantly increases the number of possible sequences, and thus significantly decreases a person's odds of winning. For example, having 20 balls to select from yields 204 = 160,000 different number sequences.

Create a Web page named pick4.html that prompts the user for the highest ball number and generates a random Pick-4 sequence. That is, if the user enters 9 as the highest ball number, then the page should generate and display four numbers from the range 0 to 9, e.g., 5-0-8-2. Note: a random integer in the range 0 to N can be generated by the expression:

Math.floor((N+1)*Math.random())



Chapter Summary


Supplemental (optional) material and exercises Solutions to odd numbered exercises