DEVTOME.COM HOSTING COSTS HAVE BEGUN TO EXCEED 115$ MONTHLY. THE ADMINISTRATION IS NO LONGER ABLE TO HANDLE THE COST WITHOUT ASSISTANCE DUE TO THE RISING COST. THIS HAS BEEN OCCURRING FOR ALMOST A YEAR, BUT WE HAVE BEEN HANDLING IT FROM OUR OWN POCKETS. HOWEVER, WITH LITERALLY NO DONATIONS FOR THE PAST 2+ YEARS IT HAS DEPLETED THE BUDGET IN SHORT ORDER WITH THE INCREASE IN ACTIVITY ON THE SITE IN THE PAST 6 MONTHS. OUR CPU USAGE HAS BECOME TOO HIGH TO REMAIN ON A REASONABLE COSTING PLAN THAT WE COULD MAINTAIN. IF YOU WOULD LIKE TO SUPPORT THE DEVTOME PROJECT AND KEEP THE SITE UP/ALIVE PLEASE DONATE (EVEN IF ITS A SATOSHI) TO OUR DEVCOIN 1M4PCuMXvpWX6LHPkBEf3LJ2z1boZv4EQa OR OUR BTC WALLET 16eqEcqfw4zHUh2znvMcmRzGVwCn7CJLxR TO ALLOW US TO AFFORD THE HOSTING.

THE DEVCOIN AND DEVTOME PROJECTS ARE BOTH VERY IMPORTANT TO THE COMMUNITY. PLEASE CONTRIBUTE TO ITS FURTHER SUCCESS FOR ANOTHER 5 OR MORE YEARS!

Loops in Java

So far we have only seen programs that do things once – but most programs involve repeated code. For example: • Asking for user input repeatedly until the user enters it correctly. • Performing iterative calculations on data. In practice very few programs do not involve iteration, or loops. Java has three basic ways of building loops: • while loops – you use these when you start the loop how many times it will go around. • do-while loops - you use these when you start the loop how many times it will go around but you do know it will be at least once. • for loops – you use these when you do know at the start of the loop how many times it will go around. These also have a newer variant that we’ll get back to in a later chapter – usually called for-each loops. First we’ll introduce each type of loop and the loop at some examples of how to use them.

While Loops

Probably the most common kind of loop – the syntax is:

while(condition) {
	code
}

As long as the condition is true, the code is executed – the condition is essentially the same as the condition we use for if statements: a Boolean expression that evaluates to true or false. We usually use the term loop body for the code inside the loop. For example.

final double TARGET = 1000.0;
double initialAmount = 500.0;
final double INTEREST_RATE = 0.05;
int i = 0;

double currentAmount = initialAmount;
while (currentAmount < TARGET) {
	currentAmount += currentAmount * 0.05;
	i++;
}

System.out.println("It takes " + i + " years at " +
	INTEREST_RATE*100 + "% interest to grow " +
	initialAmount + " to " + TARGET);

The loop body is in red. This is a simplified version of the code you need if you want to work out how long it will take for an initial amount of money to grow to a target amount given a particular interest rate. This is not something you can know before you start the loop – which is why we use a while loop.

KEY POINT – No ; at the end of While Statements

Just like the if statement, the while statement does not have a “;” after it normally, and just like the if statement it’s usually wrong. If we take the loop above:

//WRONG!
while (currentAmount < TARGET) ;
{
	currentAmount += currentAmount * 0.05;
	i++;
}

Again we’ve added an incorrect “;” in read – so this says “while currentAmount is less than TARGET do nothing”. Since doing nothing will not change whether currentAmount is less than TARGET or not, if currentAmount starts off less than TARGET this will never change and the loop will never end.

KEY POINT: Infinite Loops

One risk with loops is that – usually by mistake – you end up with one where the condition never changes to false, and so the loop never ends. This is called an infinite loop (also the name Apple chose for the road it built it’s main headquarters on for some reason). Of course loops are never really infinite – they finish when you terminate the program. But you need to be careful when you’re writing code to avoid infinite loops.

KEY POINT: {..} and Loops

Just like if statements, if the body of a while loop – or any loop – is only one line long, you don’t need the {…}. But just like if statements, you should always put the {…} in.  

Complete Program

We haven’t seen a complete program for a while, so here’s the interest rate one assuming we get the initial amount from the user.

import java.util.Scanner;

class TimeToDouble {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		final double TARGET = 1000.0;
		
		System.out.print("Enter amount: ");
		
		double initialAmount = in.nextInt();
		final double INTEREST_RATE = 0.05;
		int i = 0;

		double currentAmount = initialAmount;
		while (currentAmount < TARGET) {
			currentAmount += currentAmount * 0.05;
			i++;
		}

		System.out.println("It takes " + i +
" years at " +
			INTEREST_RATE*100 +
"% interest to grow " +
			initialAmount + " to " + TARGET);
}
}

KEY POINT: Using i

One thing we’ve said is that variable names should be meaningful; and so we can’t normally use single letter names for variables. However in this case we have used i. Using i (and j, k, l) is a bit of an exception when we need variables to count things in loops. From the very earliest days of programming in high level languages (the mid 1950s) i (and j, k, l) have been used for counters (especially loop counters) and so they are traditional and so widely-understood. Which means it’s OK to use them but only as counters.

Do-While loops

These are very commonly used when you are getting – and checking – input; because you have to ask for the input at least once, so you know it will go around at least once. The syntax is:

do {
	code
while(condition);

KEY POINT: This One Does Have a ;

Note – unlike the other kinds of loops (and if statements) do-while loops do have a “;” at the end.

As an example of a do-while loop, this code repeatedly asks the user to enter a string until they enter either “yes” or “no” – this is something that you will often find useful.

Scanner in  = new Scanner(System.in);
String input;
do {
	System.out.print("Enter either yes or no.");
	input = in.nextLine();
} while (!input.equals("yes") && !input.equals("no"));	

This loop continues as loop as the input is not equal “yes” and it’s not equal “no”.

Aside: equalsIgnoreCase

One problem with the code above is that it only accepts “no” and “yes” in lower case – what about “No” or “Yes”; or “NO” or “YES”? We could check for each of these but the code would be very complex. Fortunately we can write:

…
} while (!input.equalsIgnoreCase(“no”) &&  
    !input.equalsIgnoreCase(“yes”));

equalsIgnoreCase checks if two strings are equal regardless of their case. Better yet, we should write something like:

final String END = “no”;
final String CONT = “yes”;
…
} while (!input.equalsIgnoreCase(END) &&
         !input.equalsIgnoreCase(CONT));

By using final strings like this we can, for example, make our code independent of language. For example, by just changing two words:

//Language is Greek
final String END = “όχι”;
final String CONT = “ναί”;
…
} while (!input.equalsIgnoreCase(END) &&
         !input.equalsIgnoreCase(CONT));

For Loop

The last kind of loop differs in that it’s meant to be used when we know when the loop starts how many times it will go around. However, things are a little complicated and first we need a bit of history.

’Traditional’ For Loops

The syntax of older programming languages varied but they usually had the same kind of for loops. For example, in Pascal:

for i := 0 to 10 do begin
	(* code *)
end

is a loop that:
•	declares a variable i;
•	that starts at 0; 
•	ends at 10; and
executes some code ten times  - comments in Pascal are between (* and *); and begin and end take the place of { and }. You can also count down:

for i := 500 downto -20 do
	…

The start and end values can also be variables – but you can only count in steps of 1. This is how most for statements worked, with some variations. Notice that it’s only possible with this kind of statement to write for loops where you know before the loop starts how many times it will go around.

For Loops in Java

The designers of one of the ancestor languages of Java (called C) decided to generalize for loops and make them more flexible. The syntax is:

for(start condition; end condition; update {
	code
}
 

Rewriting the two Pascal loops above we get:

for (int i = 0; i <= 10; i++) {
	//code
}

and

for (int i = 500; i >= -20; i--) {
…

• The first part of loop before the first “;” defines the initial condition – in this case it declares an integer variable i and sets the initial value. • The second part (between the two “;”) defines the end condition – while the condition is true the loop continues. • The final part is not present in the Pascal version – it says what happens at the end of each loop. In the first case we add one to i and in the second we subtract one. The reason this is more flexible is that we can put more or less whatever code we want in the three parts (including nothing; see below). The examples above are very common in practice, but we can also be more flexible. One example is that we don’t have to count up (or down) by one for each loop. For example, the following code prints out only odd numbers up to END_VALUE:

for (int i = 1; i < END_VALUE; i +=2) {
	System.out.println(i);
}

This flexibility is very helpful – but also dangerous for two reasons.

It encourages ‘cleverness’ – for example you can re-write the odd number program as:

for (int i = 1; i< END_VALUE; System.out.println(i), i += 2);

In this case the “;” at the end of the line is deliberate – we want the loop body to be empty because we’ve put all the code in the last part of the for loop. Notice the two parts are separated by a “,” – this is called the comma operator and can be used to join bits of code in a for loop: but it’s rarely a good idea (so don’t do it).

It blurs the line between for and while loops – we’ll talk about this a bit more later – first another example.

Above we had a program that computed how many years it would take for an amount of money to grow to a target amount. Suppose instead you want to know how much money you will have after a specific number of years? This is a place to use a for loop because you know how many years you will be making the calculation for.

double initialAmount = 500.0;
final double INTEREST_RATE = 0.05;
final int NO_OF_YEARS = 15; 

double currentAmount = initialAmount;

for(int i = 0; i < NO_OF_YEARS; i++) {
	currentAmount += currentAmount * INTEREST_RATE;
}

System.out.println("After " + NO_OF_YEARS + " years " +
			initialAmount + " will be worth " + 
			currentAmount);

Counting Loops and Off-by-One Errors

Notice that in our example above the value of i starts at zero. But the continues only as long as i is less than NO_OF_YEARS. This means that the value of i ranges from 0..NO_OF_YEARS-1, so the total number of loops (iterations, or repetitions) is NO_OF_YEARS, which is correct. We could equally change it to:

for(int i = 1; i <= NO_OF_YEARS; i++)

where we start with i equal to one and continue as long as it is less than or equal to NO_OF_YEARS. This means that the value of i ranges from 1..NO_OF_YEARS – which is still equal to NO_OF_YEARS (which is still correct).

It does not really matter which of these you choose – though ‘traditionally’ we start counting from zero in Computer Science so you would normally pick the first one. The thing to avoid though is mixing them up:

for(int i = 1; i < NO_OF_YEARS; i++)

In this case, i only ranges from 1..NO_OF_YEARS-1, so there are only NO_OF_YEARS-1 interations.

for(int i = 0; i <= NO_OF_YEARS; i++)

In this case, i ranges from 0..NO_OF_YEARS, so there are only NO_OF_YEARS+1 interations.

In both cases the number of iterations is wrong by one – we call this kind of error (which is very common) an off-by-one error. When writing loops (of any kind) you do need to be careful to ensure that the loop iterations the correct number of times (and not one too many or too few).

Loop Counters and Scope

In chapter 5 on Scope we said that the scope of a variable was the {…} it was declared in. Things are slightly different for for loops because the loop counter is declared outside the loop. So as a special case the loop counter declaration is considered to be in the scope of the loop body:

for(int i = 0; i < NO_OF_YEARS; i++) {
	currentAmount += currentAmount * INTEREST_RATE;
}

The variable declaration (in red) is considered to be in the scope of the loop body (also in red).

Using the Loop Counter Outside the Loop One thing that does cause confusion sometimes, and related to scope, is using the loop counter outside (usually after) the loop. Notive in the example above we defined a variable called NO_OF_YEARS. If we tried to rewrite our code like this

//WON’T COMPILE
for(int i = 0; i < NO_OF_YEARS; i++) {
	currentAmount += currentAmount * INTEREST_RATE;
}

System.out.println("After " + i + " years " +
			initialAmount + " will be worth " + 
			currentAmount);

using i (in red again) instead of NO_OF_YEARS, the code would not compile because we are trying to use i outside its scope. In this case it’s not a huge problem but there are time when it can be something you need (or at least want) to do. The solution is to just move the declaration of i to before the loop:

//This works
int i = 0;
for(; i < NO_OF_YEARS; i++) {
	currentAmount += currentAmount * INTEREST_RATE;
}

System.out.println("After " + i + " years " +
			initialAmount + " will be worth " + 
			currentAmount);

because now the declaration of i is in the scope of the println statement that uses it. Notice that now the first part of the for loop is empty – this is fine and it’s not a problem if one or more parts are empty (though if they are all empty – for(;;) – you will have an infinite loop).

Interchangeable While and For Loops – Danger!

One of the consequences of the more general kinds of for loop used in Java is that they have become functionally identical to while loops. This makes it very easy to use the wrong one. Here’s an example – this should be a for loop (shown first) but we can write it as a while loop:

for (int i = 0; i < 10; i++) {
	//code
}

identical to:

int i = 0;
while (i < 10) {
	//code
	i++;
}

Strictly speaking, the second loop is not quite identical to the first because the scope of the variable i is wider – but this is a very minor point.

Because for loops are so general, we can do the same thing the other way around – here’s an example of a while loop that calculates the greatest common divisor of two integers valueA and valueB – first as a while loop and then rewritten as a for loop (again colour coded):

//Assume a & b integers already declared
a = valueA;
b = valueB;
while(b !=0 ) {
	int temp = b;
	b = a % b;
	a = temp;
}
System.out.println("Greatest common divisor of " +
	valueA + " and " + valueB + " is " + a);

and re-written:

for(a = valueA, b = valueB; b != 0;) {
	int temp = b;
	b = a % b;
	a = temp;
}
System.out.println("Greatest common divisor of " +
	valueA + " and " + valueB + " is " + a);

Notice again this is an example of a for loop where part is empty.

Programming Style and Loops – Structured Programming

All the loops we’ve seen so are are quite structured – we test if we are going to continue to loop at the beginning or end; we cannot exit the loop from the middle – only if the test at the start (or end) tells us the loop should finish. However, there are sort of unfortunately, two commands in Java that let us change that. This section explains what they are and why you should not use them.

The break Statement

Recall the last chapter where we discussed switch statements:

switch(card) {
case “Ace” : 	//do something
		break;
case “King”:	//do something else
		break;
…
case “one”:	//do one last thing
		break;
}

The break statement is not only used as part of the switch statement – it also has a separate meaning on it’s own. Simplistically, if the command ‘break’ appears in a program, it means jump to the first line of code after the immediately following bracket .You can see that’s exactly what break does in a switch – it causes execution to jump to the code following the switch, after the bracket that ends the switch.

The continue Statement

Very similar to the break statement, the continue statement does not exit a loop, instead it jump to the test to see if the loop should continue. This code adds up only the odd numbers between 1 and 100 – the if statement checks if the value of i is even, and if it is, it jumps straight back to the for statement, skipping the line sum += i;

Structured Programming – and Why not to use break and continue

This looks like it might come in handy – and very occasionally, it does (and so does break). But more usually it cases problems. Very occasionally – usually when you’re dealing with some error condition or special case deep in a load of nested loops – these commands can come in handy. But: • Usually there’s a better way. • They are open to abuse and lead to very bad code. The point of this loop is to ask the user if they want to take another card, and if they do, to add a random number in the range 1 to 10 to their current total; and to keep doing that until they either stop asking or they go over the maximum allowed value.

• You ask the user for input • If they type “twist” you add a random number to their score • The loop ends when they either don’t type “twist” or they go over the maximum value.

KEY POINT: Structured Programming

Practice and experience has shown that this type of loop is much harder to understand than the first kind, and much harder to change without introducing errors than the first kind. Code in which loops only start and end in one place (all the ones we’ve seen except the examples in this section) are categorized as examples of structured programming, and that is what we should aspire to do where possible. There are cases where not doing this is clearer, but: • they are rare • none of them will come up in your first year of programming So don’t use break and continue in loops

Advanced Interlude – Edsger Dijkstra and Goto Considered Harmful

If you want to know more about this try googling Edsger Dijkstra Goto Considered Harmful (the name is spelt correctly – it’s Dutch – and pronounced ‘eds-ger dike-stra’). In early programming languages the primary control command was the ‘goto’ statement that allowed you to jump wherever you wanted within your code. Prof Dijkstra wrote a letter in 1968 – normally referred to as ‘Go To Statement Considered Harmful’ – to the journal Communications of the Association for Computing Machinery in which he criticized this, leading to the development of modern structured programming. The ‘break’ and ‘continue’ statements are basically ‘controlled’ versions of goto and the same principles apply – and they should usually be avoided for the same reasons. Computer Science


QR Code
QR Code loops_java (generated for current page)
 

Advertise with Anonymous Ads