Contents |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
So far, we have only considered programs where all instructions are executed sequentially. However, such programs are severely limited in their functionality. A program only achieves its true power when instructions are executed multiple times or only under certain conditions. Only then can it perform non-trivial tasks.
If you want to execute a statement only under a specific condition , you use `if` . An example would be...
if (x < 0) x = -x;
The instruction x = -x is therefore only executed if x is negative. This corresponds to calculating the absolute value of x.
In general, the syntax of if is
if ( condition ) statement block
Note that the condition must be enclosed in parentheses . And a statement block is either a single statement (with a semicolon ) or a block of statements enclosed in curly braces {...} .
Example:
if (x < 0)
{
System.out.println("x was negative");
x = -x;
}
You can also specify the alternative.
if (x < 0)
{
System.out.println("x was negative");
x = -x;
}
else
{
System.out.println("x was positive");
}
The else clause is only executed if the condition is false. In this example, the parentheses after else are unnecessary because the block contains only one statement. Therefore, the general syntax is...
if ( condition ) statement block else statement block
As before, a statement block can also be a single statement with a semicolon (;) . If multiple if statements are nested, else refers to the preceding if statement , regardless of indentation.
Rule: else always refers to the preceding if.
Example:
if (needpositive)
if (x < 0) x = -x;
else System.out.println("x was already positive");
Here, `needpositiv` is a boolean variable that should contain a flag indicating whether the test should be performed or not. The indentation of `else` is irrelevant; it always refers to...
if (x < 0) ...
It is probably better to enclose the statements in nested if statements using {...} .
One should always ensure that one's programs are perfectly readable.
Programmers often use the following programming style with nested conditions.
if (x < 0) System.out.println("x is negative.");
else if (x == 0) System.out.println("x is 0.");
else if (x > 0) System.out.println("x is positive.");
As a warning, I'd like to point out that there's no need for a semicolon ( ; ) after blocks {...} . This would only create an empty statement . If an else statement follows the block , it won't even work with a semicolon .
These loops are used to execute program sections multiple times with changed values . Loops are terminated when a predefined condition is met or no longer met.
The simplest loop is the while loop. A block of instructions is executed as long as the termination condition is true. The following example, for instance, counts up to 10.
int i = 1;
while (i <= 10)
{
System.out.println(i);
i++;
}
This loop can be formulated as follows:
The general syntax of the while loop is...
while ( condition ) statement block
As with the if statement , the condition must be enclosed in parentheses .
The termination condition is checked before each block of instructions is executed. If it is false from the outset , the loop will never run.
It's essential to ensure that the termination condition is eventually met. Otherwise, a loop will occur that can only be ended by terminating the program. In Java, this can be done by pressing Ctrl+C at the command line. A loop is, for example...
while (true)
{
System.out.println("Please press Ctrl-C");
}
This loop continuously prints the same text. The program must be terminated by the user.
The condition can also be placed at the end.
do statement block while ( condition );
Here, the loop is executed first, and then the condition is tested. If it 's false , the loop terminates. Therefore, the loop will always execute at least once. Otherwise, it's no different from a while loop.
Our example, which counts from 1 to 10, looks like this.
int i = 1;
do
{
System.out.println(i);
i++;
}
while (i<=10);
The difference to the while loop becomes apparent when you initially set i = 10. In this case, only the number 10 is output using do ... while . The difference is even more striking when you set i = 11. It also outputs 11.
Another, more compact form of loop is the for loop, which is primarily a simplification for simple counting loops . First, an example that again counts from 1 to 10.
int i; for (i = 0; i <= 10; i++) System.out.println(i);
The general syntax is
for ( initial statement ; condition ; loop statement )
statement block
|
initial instruction |
Executed before the first loop iteration. In the example above, i is set to the value 0 . |
|
loop instructions |
This instruction is executed at the end of each loop iteration. In the example above, i is incremented by 1 . |
|
condition |
This expression is evaluated before each iteration (including the first). The expression must be a boolean . If the evaluation is positive, a new iteration starts; otherwise, the loop terminates. In the example above, the loop terminates when i becomes greater than 10 (i.e., it executes as long as i <= 10 ). |
The following example counts backwards from 10 to 1.
int i; for (i = 10; i >= 1; i--) System.out.println(i);
It is advisable to use the for loop only for simple counting loops, otherwise the syntax becomes confusing.
You can also declare the variable directly within the loop. The last example then looks like this:
for (int i = 10; i >= 1; i--) System.out.println(i);
The variable is then only valid within the loop . Therefore, the final value cannot be retrieved afterward. While it's possible to declare loop variables outside the loop, this is not recommended for clarity.
You can also use several simple commands, separated by commas, as an initial instruction. Example
for (int i = 0, k = n; i < n; i++, k--) System.out.println(i + ", " + k);
This increments i and decrements k . It's unclear whether such compactness might actually detract from the clarity. The same effect can be achieved more clearly.
k=n;
for (int i = 0; i < n; i++)
{
System.out.println(i + ", " + k);
k--;
}
Important! The following loop is incorrect:
int i;
for (i = 0; i <= 10; i++);
{
System.out.println(i);
}
The semicolon before the loop block is incorrect. It is interpreted as an empty command, which is then executed 10 times. After that, the loop block is executed once with the value 10 for i . This error is surprisingly common and difficult to find.
As a first example, we generate 100 random numbers between 0 and 1. The routine `Math.random()` returns a (pseudo-) random number of type ` double` between 0 and 1. The two end values do not occur, and the numbers are otherwise evenly distributed within the interval. Our goal is to output the largest of the generated numbers. For this, we use the following algorithm:
The program looks like this:
public class Test
{
public static void main (String args[])
{
int i;
double max;
max=Math.random(); // First random number
for (i=2; i<=100; i++)
{
double x = Math.random(); // next number
if (x > max) max = x; // Update maximum
}
System.out.println("Maximum :"+max);
}
}
As a second example, we nest two loops inside each other.
for (i=1; i<10; i++)
{
for (j=1; j<10; j++) System.out.print(i*j+" ");
// Print one line of the multiplication table.
System.out.println(""); // Start a new line.
}
The program prints the multiplication table.
1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81
The subroutine System.out.print prints without a line break. This allows all 10 values to be printed in one line before a line break begins the next line.
The formatting leaves something to be desired, as the numbers are displayed with varying widths. Anticipating future chapters, we will format the numbers using String.format() . In this case, we will use the format "%2d" , which displays an integer decimal with two digits.
public class Test
{
public static void main(String args[]) {
int i, j;
for (i = 1; i < 10; i++)
{
for (j = 1; j < 10; j++)
{
int p = i * j;
System.out.print(String.format("%2d ", p));
}
System.out.println("");
}
}
}
Note the declaration of a local variable within the loop block. This variable is only valid within the for loop. The output is now much cleaner.
1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81
A loop can also be broken . This is done using the `break` statement. It is usually called within a condition, that is, inside an `if` statement. For example, the following loop only counts up to 5 because it is broken at that point by the `break` statement .
for (int i=1; i<=10; i++)
{
System.out.println(i);
if (i==5) break;
}
There can of course be multiple break statements in a loop.
The `continue` command works similarly . However, it doesn't break the loop, but only skips the remainder of that loop iteration. The loop's termination condition is then checked, and in the case of `for` loops, the loop statement is executed beforehand.
With nested loops, it's also possible to jump to an outer loop. Labels are used for this purpose.
loop: while (condition)
{
...
break loop;
...
}
In this example, the `break` command exits the specified `while` loop, even if it is contained within an inner loop. This achieves the effect of an absolute jump.
loop: while (true)
{
...
if (error) break loop;
...
break;
}
This isn't actually a loop, since there's a break at the end . It only makes sense if a continue statement appears somewhere beforehand. You should only use such constructs if they reflect the logical flow of the code.
Note: break and continue, especially with labels, should only be used if they do not obscure the program logic.
This statement is used to perform conditional statements . It tests an int expression to see if it equals certain constants. The general syntax is:
switch ( expression )
{
case constant1 : instructions
case constant2 : instructions
...
default : instructions
}
In this context, instructions means a series of instructions, each followed by a ; , or a block of instructions enclosed in {...} .
Note: Each series of instructions must end with a break statement; otherwise, the instructions of the next case will also be executed.
Example:
switch (n)
{
case 0 : System.out.println("zero"); break;
case 1 : System.out.println("one"); break;
case 2 : System.out.println("two"); break;
case 3 : System.out.println("three"); break;
default : System.out.println("Cannot count that much!");
}
The constants must be true constants that the compiler can evaluate. The expression following the switch statement is then compared with the individual constants, and the program jumps to the statements after the corresponding case .
Enumerations allow you to set predefined sets of values. The alternative is to define a series of int variables with predefined values. However, this method is inferior because the elements of an enumeration don't actually have anything to do with int values , and the rigid binding is too inflexible and unclear.
enum color {red, green, blue};
public class Test
{
static public void main (String args[])
{
Color f;
f=color.red;
System.out.println(f);
switch (f)
{
case Red : System.out.println("OK, Red!"); break;
default : System.out.println("Not red!");
}
}
}
The declaration is done simply like that of a class, but can also be made within a class in a subclass. Enumerations behave like classes in many other contexts as well. As you can see, the switch function works very well with enumerations.
The following more complicated example finds the smallest divisor of a natural number, or outputs that the number is prime.
public class Test
{
public static void main (String args[])
{
int n=1019,i;
// Test n for divisors:
if (n%2 == 0) System.out.println("2 divides "+n); // 2 divides n
else // 2 does not divide n!
{
i=3; // test 3,5,7,9,...
double ns = Math.sqrt(n); // only needed up to the square root
while (i <= ns)
{
if (n%i == 0) // Divisor found!
{
System.out.println(i + " divides " + n);
break; // Loop is broken
}
i+=2;
}
if (i>ns) System.out.println(n + " is prime");
// In this case, no divisor was found.
}
}
}
Note that you only need to check the numbers 2, 3, 5, 7,... as divisors. Furthermore , if n is not prime, there must always be a divisor less than the square root of n .
Since this program is very mathematically intensive and quite complex, we will describe its logic verbally here.
Suppose a debt of 100,000 is repaid in annual installments of 8,000 at an interest rate of 7%. When will the debt be paid off?
public class Test
{
public static void main(String args[])
{
double K = 100000, R = 8000, P = 0.07;
int i = 0;
while (K > 0)
// Termination when the capital has been repaid
{
K = K + K * 0.07 - R; // Capital + Interest Rate
i++;
// Disbursement of the remaining debt:
System.out.println(String.format("%2d", i) + ": "
+ String.format("%10.2f", K));
}
}
}
To format the output of the capital to two decimal places and a total of 10 places (right-aligned), we use the format "%10.2f" .
The output is
1: 99000.00
2: 97930.00
3: 96785.10
4: 95560.06
5: 94249.26
6: 92846.71
7: 91345.98
...
25: 36750.96
26: 31323.53
27: 25516.18
28: 19302.31
29: 12653.47
30: 5539.21
31: -2073.04
So, after 31 years, the debt has been paid.
First, we simply want to output the ASCII character set. These are the char values from 32 to 127. Values 0 to 31 are special characters, and from 128 onwards we find national characters.
public class Test
{
public static void main (String args[])
{
int i,j;
for (i=2; i<16; i++) // 14 lines
{
for (j=0; j<16; j++) System.out.print((char)(16*i+j));
// 16 characters per line
System.out.println(" "+i*16+" - "+(i*16+15));
// At the end, section AB
// of the characters in this line.
}
}
}
The output is
!"#$%&'()*+,-./ 32 - 47
0123456789:;<=>? 48 - 63
@ABCDEFGHIJKLMNO 64 - 79
PQRSTUVWXYZ[\]^_ 80 - 95
`abcdefghijklmno 96 - 111
pqrstuvwxyz{|}~ 112 - 127
...
This corresponds to the first Unicode characters. After that come characters that are difficult to display in an HTML file like this. This is where we encounter the problem of Unicode encoding, which we will discuss later.
Now we want to define the iteration rule.
x(n+1) = (x(n)+2/x(n))/2;
with the starting value
x(0) = 2;
Calculate. This sequence converges to the square root of 2. In implementing this calculation, we store all the variables x(n) in the same variable x. The process is therefore
public class Test
{
public static void main (String args[])
{
double x = 2; // Initial value
while (Math.abs(x*x-2) > 1e-12) // Termination condition
x = (x + 2/x)/2; // Iteration
System.out.println(x); // Output of the final value
}
}
The value of x is therefore always replaced by the new value. We choose the termination condition that x^2 is close enough to 2.
As a second example, the bisection method for determining the solution of the equation is used.
e^x=4x
The function is programmed between 0 and 1. At the left end of the interval, e^0 > 0, and at the right end, e^1 < 4. We calculate a sequence of intervals that approximate the value to an arbitrarily high degree. All these intervals have the property that the function value of e^x - 4x is less than 0 on the left and greater than 0 on the right.
public class Test
{
public static void main (String args[])
{
double a=0,b=1,m,y;
while (ba>1e-10) // Terminate if interval is small enough
{
m = (a + b) / 2; // Calculate the middle
y = Math.exp(m) - 4 * m; // and value in the middle
if (y > 0) a = m; // Take the right half-interval
else b = m; // Take the left half-interval
}
System.out.println(a + "," + b); // Print the result
}
}
The result is
0.3574029561714269,0.3574029562296346