The ability to perform repetitive calculations is important in computer algorithms. This is enabled through the use of loop structures. Loops can be written to execute the same code statements a prescribed number of times, or they can be written so that loop execution (or termination) is based on conditions that change while statements in the loop are being executed. The former situation uses count-controlled loops and the latter uses conditional loops.
4.8.1
Count-Controlled Loops
Count-controlled loops are managed with the for keyword. The general syntax of a count-controlled loop is:
for (counter= {expression giving on initial value of counter}; {expression giving high (or low) value of counter};
{expression controlling incrementing (or decrementing) of counter})
The for keyword is followed by three statements inside a pair of parentheses. The first statement sets the initial value of a counter. You can give the identifier name—
counter in the above example—any name you like. The second expression sets condi-tions under which the loop should continue to execute; the loop continues to execute as long as the value of the second expression is true. The third expression controls how the counter is incremented or decremented. It is up to you to make sure that these three
100 4 Fundamentals of the JavaScript Language
4
related expressions are consistent and will actually cause the loop to terminate. For example, the loopfor (i=1; i=12; i+=2)
will never terminate because i will never equal 12. Perhaps you meant to write the second expression as i<=12;. If so, then the loop will execute for i=1, 3, 5, 7, 9, and 11.
Now, consider Document 4.7, which displays the integers 0–10, in order. The counter k is initialized to 1. It is incremented in steps of 1, and the loop executes as long as k is less than 10. Use of the shortcut incrementing or decrementing operators, as in k++, is very common in for loops.
Document 4.7 (counter2.htm)
<html>
<head>
<title>Counter</title>
<script>
var k;
document.write("Here's a simple counter: "+"<br />");
for (k=0; k<=10; k++) { //curly brackets optional document.write(k+"<br />");}
</script>
</head>
<body>
</body>
</html>
For this example, a statement block enclosed in curly brackets following the for… loop is not required because only one statement is executed in the loop. Document 4.8 shows a version of Document 4.6 which counts backward from 10.
Document 4.8 (countdown2.htm)
<html>
<head>
<title>Countdown</title>
<script>
var k;
document.write("Start launch sequence!"
+"<br />");
101 4.8 Loop Structures
for (k=10; k>=0; k--) { //curly brackets optional document.write(k+"<br />");
}document.write("FIRE!!");
</script>
</head>
<body>
</body>
</html>
Recall that a for… loop was used previously in Document 4.3. Now would be a good time to look back at that code and make sure you understand how that loop worked.
4.8.2 Conditional Loops
It is often the case that conditions under which repetitive calculations will or will not be executed cannot be determined in advance. Instead, conditions that control the execution or termination of a loop structure must be determined by values calculated inside the loop, while the script is running. Such circumstances require conditional loops.
There are two kinds of conditional loops: pre-test and post-test loops. The statements in pre-test loops may or may not be executed at all, depending on the original values of loop-related variables. Post-test loops are always executed at least once, and the values of loop-related variables are tested at the end of the loop. The syntax is slightly different:
pre-test loop:
while ({logical expression}) {
{ statements that result in changing the value of the pre-test logical expression}
}
post-test loop:
do {{ statements that result in changing the value of the post-test logical expression}
} while ({logical expression});
Conditional loops can always be written either as post- or pre-test loops. The choice is based on how a problem is stated. Consider this problem:
102 4 Fundamentals of the JavaScript Language
4
A small elevator has a maximum capacity of 500 lb. People waiting in line to enter the elevator are weighed. If they can get on the elevator without exceeding the load limit, they are allowed to enter. If not, the elevator leaves without trying to find some-one who weighs less than the person currently first in line. If the elevator is overloaded, it crashes. It is possible that there might be a large gorilla in line, weighing more than 500 lb. This gorilla shouldn’t be allowed on the elevator under any circumstances.Write a document that will supply random weights for people (or gorillas) waiting in line, control access to the elevator, and stop allowing people (or gorillas) to enter if the weight limit would be exceeded.
One solution to this problem is shown in Document 4.9.
Document 4.9 (gorilla1.htm)
<html>
<head>
<title>The elevator problem (with gorillas).</title>
<script language="javascript" type="text/javascript">
var totalWeight=0.,limitWeight=500.,maxWeight=550.;
var newWeight;
do {newWeight=Math.floor(maxWeight*(Math.random()%1))+1;
if ((totalWeight + newWeight) <= limitWeight) { totalWeight += newWeight;
document.write(
"New weight = " + newWeight + " total weight = "
+totalWeight + "<br />");
newWeight=0.;
}else document.write("You weigh " + newWeight +
" lb. I'm sorry, but you can't get on.");
} while ((totalWeight + newWeight)
<= limitWeight);
</script>
</head>
<body>
</body>
</html>
This solution to the problem uses the Math.random() method to generate random weights between 0 and 500 lb. The calculations are done inside a post-test loop. The code is arranged so that the effect of adding a new person to the elevator is tested before the person is allowed on the elevator. It is left as an exercise to rewrite this loop as a pre-test loop.
In principle, count-controlled loops can also be written as conditional loops. However, it is better programming style to reserve conditional loop structures for problems that
103 4.8 Loop Structures
actually need them. Clearly, Document 4.9 is such a problem because there is no way for the script to determine ahead of time what weights the Math.random() method will generate. Another example of a problem that demands a conditional loop calculation is Newton’s algorithm for finding the square root of a number.
Given a number n:
1. Make a guess (g) for the square root of n. n/2 is a reasonable guess.
2. Replace g with
(
g n g+ /)
/ 2.3. Repeat step 2 until the absolute difference between g2 and n is smaller than some specified value.
This algorithm is easy to write as a conditional loop. Consider Document 4.10.
Document 4.10 (newtonSqrt2.htm)
<html>
<head>
<title>Newton's square root algorithm</title>
<script language="javascript" type="text/javascript">
var n=prompt("Enter a positive number:");
n=parseFloat(n);
var g=n/2;
do {g = (g + n/g)/2.;
} while (Math.abs(g*g-n) > 1e-5);
alert(g+" is the square root of "+n+".");
</script>
</head>
<body>
</body>
</html>
This algorithm is imple-mented as a post-test loop
because a reasonable assumption is that the calculation inside the loop will always need to be done at least once. In fact, considering that the initial guess for the square root of n is n/2, this assumption is true for all values of n except 4. The statement g=(g+n/g)/2; is an excellent example of how an assignment operator differs from the same symbol (=) when it is used in an algebraic context. This kind of “replacement assignment” is often seen in conditional loops.
The terminating condition while (Math.abs(g*g-n)>1e-5); is important. It is not obvious whether g2 will be larger or smaller than n. So, you must test the absolute value of g2 − n to ensure that the value being compared to 10−5 is always positive (because any negative number is less than +10−5).
104 4 Fundamentals of the JavaScript Language