More about the For Statement

Site: Saylor Academy
Course: CS101: Introduction to Computer Science I
Book: More about the For Statement
Printed by: Guest user
Date: Friday, February 4, 2022, 4:56 PM

Description

This chapter discusses the 'for' loop in greater detail, as well as the scope of variables in the 'for' loop.

1. More about the for Statment

The for is a useful and frequently used statement. This chapter discusses more details about the for you should know in order to make full use of it.

Chapter Topics:

      • Declaring the loop control variable in the for statement
      • Scope of a loop control variable
      • Floating point increments

Question 1:

(Review:) What is the advantage of a for statement over a while statement?


Source: Bradley Kjell, http://programmedlessons.org/Java9/chap25/ch25_01.html
Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 License.

2. Declaring the Loop Control Variable


Answer:

All three aspects of the loop

  1. Initializing the loop,
  2. testing the ending condition, and
  3. changing the value of what is being tested,

are done in one statement. This makes it easier to check if you have done things correctly.

Declaring the Loop Control Variable

Here is a counting loop:

int count;

. . . . . .

for ( count = 0; count < 10; count++ )
System.out.print( count + " " );

The loop control variable count has been declared somewhere in the program, possibly many statements away from the for statement. This violates the idea that all the parts of the loop are combined in one statement. It would be nice if the declaration of count were part of the for statement. In fact, this can be done, as in the following:

for ( int count = 0;  count < 10; count++ )
System.out.print( count + " " );

In this example, the declaration of count and its initialization have been combined.

However, there is an important difference between this program fragment and the previous one:

Annotation 2020-03-19 215454

The following is NOT correct:

for ( int count = 0;  count < 10; count++ )    
System.out.print( count + " " );

// NOT part of the loop body
System.out.println(
"\nAfter the loop count is: " + count );

Since the println() statement is not part of the loop body, count cannot be used here. The compiler will complain that it "cannot find the symbol: count" when it sees this count. This can be a baffling error message if you forget the scope rule.


Question 2:

Is the following code fragment correct?

    int sum = 0; for ( int j = 0; j < 8; j++ ) sum = sum + j; System.out.println( "The sum is: " + sum );

3. Scope


Answer:

Yes. The variable sum is declared outside of the for statement and can be used inside and outside of the loop body.
The variable j is declared inside of the for statement and can be used only in the body of the loop.

Scope

The scope of a variable is the span of statements where it can be used. The scope of a variable declared as part of a for statement is that statement and its loop body. Another way to say this is:

A loop control variable declared as part of a for statement can only be "seen" by the for statement and the statements in that loop body.


Question 3:

Is the following code correct?

public class BigScope
{
  public static void main ( String[] args )
  {
    int sum = 0;

    for ( int j = 0;  j < 80; j++ )
    {
      if ( j % 7 != 0 )
        sum  = sum + j;
      else
        System.out.println( "Not added to sum: "  + j );
    }

    System.out.println( "The final sum is: " + sum ); 

  }
}

4. Same Name used in Several Loops


Answer:

Yes — the several uses of j are all within the for statement and its loop body.

Same Name used in Several Loops

Several for statements can use the same identifier (the same name) for their loop control variable, but each of these is a different variable which can be seen only inside its own loop. Here is an example:

public class SameName
{
  public static void main ( String[] args )
  {
    int sumEven = 0;
    int sumOdd  = 0;

    for ( int j = 0;  j < 8; j=j+2 )      // a variable named "j"
        sumEven = sumEven + j;
    System.out.println( "The sum of evens is: " + sumEven ); 

    for ( int j = 1;  j < 8; j=j+2 )      // a different variable named "j"
        sumOdd  = sumOdd + j;
    System.out.println( "The sum of odds is: " + sumOdd );
  } 
}

The two loops work correctly, and don't interfere with each other, even though each one has its own variable named j.

Question 4:

Is the following code correct?

public class SameName
{
  public static void main ( String[] args )
  {
    int sumEven = 0;
    int sumOdd  = 0;

    for ( int j = 0;  j < 8; j=j+2 )
        sumEven = sumEven + j;

    System.out.println( "The sum of evens is: " + sumEven ); 

    for ( j = 1;  j < 8; j=j+2 )      // Notice the change in this line
        sumOdd  = sumOdd + j;                     

    System.out.println( "The sum of odds is: " + sumOdd );
  } 
}

5. Keep things local


Answer:

No. The second for loop is trying to use a variable j that is not defined at that point.
(The first for statement declares a j than can only be seen within that loop.)

<table width=100% style="border: 5px double red;">

    <tbody>

        <tr>

        </tr>

        <tr>

            <td style="border: 5px double red;">

                <pre><pre>TEXT</pre></pre>

            </td>

        </tr>

    </tbody>

</table>

Keep things local

Here is another version of the program, which is syntactically correct, but is not nicely done.

public class FoolishTypist
{
  public static void main ( String[] args )
  {
    int sumEven = 0;
    int sumOdd  = 0;
    int j;     // Same "j" used for both loops.

    for ( j = 0;  j < 8; j=j+2 )
        sumEven = sumEven + j;

    System.out.println( "The sum of evens is: " + sumEven ); 

    for ( j = 1;  j < 8; j=j+2 ) 
        sumOdd  = sumOdd + j;                     

    System.out.println( "The sum of odds is: " + sumOdd );
  } 
}

It is best to keep sections of code self-contained. With this (unwise) version, both loops depend on something distant from themselves. Although this program is clear enough, a longer program might be harder to understand. Here, for instance, is a typical hard to understand program:

public class FoolishTypist
{
  public static void main ( String[] args )
  {
    int sumEven = 0;
    int sumOdd  = 0;
    int j = 0;
    int i = 1;

    for ( j = 0;  j < 8; j=j+2 )
        sumEven = sumEven + j;

    System.out.println( "The sum of evens is: " + sumEven ); 

    for ( i = 1;  i < 8; i=i+2 ) 
        sumOdd  = sumOdd + j;                     

    System.out.println( "The sum of odds is: " + sumOdd );
  } 
}

Question 5:

  1. Will this new program compile?
  2. Will it run?
  3. Is it correct?

6. Floating Point Loop Control


Answer:

  1. Will this new program compile?
    • Yes. The compiler will not complain about anything.
  2. Will it run?
    • Yes. It will run without any error messages.
  3. Is it correct?
    • No. There is an error which may be hard to find because the two loops are not self-contained.

Floating Point Loop Control

For counting loops it is best to use an integer for the loop control variable. However, it is legal to use a floating point control variable and to use fractional increments. The following program prints a table that displays x and ln(x) for values of x from 0.1 up to about 2.0:

public class LogTable
{
  public static void main ( String[] args )
  {
    System.out.println( "x" + "\t ln(x)" );

    for ( double x = 0.1; x <= 2.0; x = x + 0.1 )
      System.out.println( x + "\t" + Math.log( x ) );
  } 
}

It compiles correctly, and runs. But its output is not pretty:

x                        ln(x)
0.1                     -2.3025850929940455
0.2                     -1.6094379124341003
0.30000000000000004     -1.203972804325936
0.4                     -0.916290731874155
0.5                     -0.6931471805599453
0.6                     -0.5108256237659907
0.7                     -0.35667494393873245
0.7999999999999999      -0.22314355131420985
0.8999999999999999      -0.1053605156578264
0.9999999999999999      -1.1102230246251565E-16
1.0999999999999999      0.09531017980432474
1.2                     0.1823215567939546
1.3                     0.26236426446749106
1.4000000000000001      0.336472236621213
1.5000000000000002      0.40546510810816455
1.6000000000000003      0.47000362924573574
1.7000000000000004      0.5306282510621706
1.8000000000000005      0.5877866649021193
1.9000000000000006      0.641853886172395

Remember (from a previous chapter) that floating point numbers are not always exact. In particular, 0.1 is always slightly wrong when represented using floating point, no matter how many bits are used. In the above program, errors in x accumulate, and x drifts away from the desired value.

Notice that the loop does not end with x equal to 2.0, as you would expect. The loop condition is x <= 2.0, but x evidently overshoots the value 2.0 the last time it is incremented.


Question 6:

Are integer numbers completely accurate?

7. A Loop with an Integer Variable


Answer:

Yes. 1 + 1 is always exactly 2, with integers. (But you do need to worry about overflow when the
operands get too big.)

A Loop with an Integer Variable

Often a program uses an integer loop control variable which is used to compute a floating point x for every iteration of the loop. If you do this, floating point errors will not accumulate as the loop continues. (However, the floating point division that is done each time has only 64-bit accuracy.)

public class LogTable
{
  public static void main ( String[] args )
  {
    System.out.println( "x" + "\t ln(x)" );

    for ( int j = 1; j <= 20; j++ )
    {
      double x = j/10.0 ;
      System.out.println( x + "\t" + Math.log( x ) );
    }
  } 
}           

Here is its output:

x        ln(x)
0.1     -2.3025850929940455
0.2     -1.6094379124341003
0.3     -1.2039728043259361
0.4     -0.916290731874155
0.5     -0.6931471805599453
0.6     -0.5108256237659907
0.7     -0.35667494393873245
0.8     -0.2231435513142097
0.9     -0.10536051565782628
1.0     0.0
1.1     0.09531017980432493
1.2     0.1823215567939546
1.3     0.26236426446749106
1.4     0.33647223662121284
1.5     0.4054651081081644
1.6     0.4700036292457356
1.7     0.5306282510621704
1.8     0.5877866649021191
1.9     0.6418538861723947
2.0     0.6931471805599453

The result of dividing  j by 10.0 is not completely accurate. However, dividing an integer by a power of two, is accurate (as long as the result is not too small).

Question 7:

Is 8 a power of two?

8. Nicer Table


Answer:

Yes: 2*2*2 == 8

Nicer Table

Here is the program again, this time with better accuracy because the divisor is 8, a power of two.

public class LogTable
{
  public static void main ( String[] args )
  {
    System.out.println( "x" + "\t ln(x)" );

    for ( double x = 1.0/8.0; x <= 2.0; x = x + 1.0/8.0  )
    {
      System.out.println( x + "\t" + Math.log( x ) );
    }
  } 
}      

Here is its output:

               
x        ln(x)
0.125   -2.0794415416798357
0.25    -1.3862943611198906
0.375   -0.9808292530117262
0.5     -0.6931471805599453
0.625   -0.4700036292457356
0.75    -0.2876820724517809
0.875   -0.13353139262452263
1.0     0.0
1.125   0.11778303565638346
1.25    0.22314355131420976
1.375   0.3184537311185346
1.5     0.4054651081081644
1.625   0.4855078157817008
1.75    0.5596157879354227
1.875   0.6286086594223741
2.0     0.6931471805599453

This is our best table yet! Unfortunately, because of the awkward increment value (of 1/8) the table is inconvenient for human consumption. But computing a table of numbers for display purposes is rare. Usually the numbers computed in a loop are used by the program itself for some larger task, such as drawing a picture, or for an engineering computation, and there is no particular reason to use a step size of one tenth. No human will actually look at the numbers.


Question 8:

(Thought question: ) Binary-based floating point numbers have accuracy problems. So why not build
computers that use decimal-based floating point numbers?

Hint: chocolate-chip cookies are three for a dollar. How much is one cookie?

9. End of Chapter


Answer:

Decimal-based floating point numbers have similar
problems, but with different numbers. For example
1.0/3.0 == 0.3333... without end.

All floating point schemes have these problems. 
Since binary has so many other advantages, most
computers use it. Electronic calculators sometimes
use hardware decimal-based calculations since
they always present their results to humans. Also,
mainframe computers have hardware decimal-
based instructions for use in financial calculations.

End of Chapter

Reviewing the following. Click on a subject that interests you to go to where it was discussed.