• Aucun résultat trouvé

Loop Structures

Dans le document Guide to HTML, JavaScript and PHP (Page 114-119)

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 loop

for (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

4

This algorithm will work for any positive number. Note that the algorithm does not give  exactly 3 as the square root of 9. On the other hand, if you calculate the square root of 4, it  will give exactly 2. These kinds of discrepancies are a result of how numbers are stored  and how numerical calculations are done. Newton’s square root algorithm is a numerical  approximation, so in general, it will approach the actual answer (within the specified accu- racy), but won’t necessarily give the exact answer for a perfect square. Except for annoy-ing  strings  of  zeros  and  digits—to  the  right  of  the  3  in  the  output  shown  here—these  discrepancies are usually of no practical concern. If desired, the extraneous digits can be  removed with the Math.round() or toFixed() method.

4.9

Dans le document Guide to HTML, JavaScript and PHP (Page 114-119)