Consider the following program:
In-Class Exercise 2:
Edit, compile and execute the above program.
Now let's examine key parts of this program:
- First, i is the name of a "box" (of sorts).
- The term used for "box" is variable.
=> i is a variable.
- Variables must be "typed"
=> i can only store integers.
- To create and name a variable, we use a variable declaration:
- Here, int is a reserved word in Java.
- To put something in a variable, we use assignment
=> with the repurposed = (equals) sign.
- When we print a variable, what gets printed is its value.
=> Thus, the number 5 gets printed
Next, let's look at assignment between variables:
- This is the analogue of cloning.
- Consider this addition to the above program:
- We say, in short, "i is assigned to j".
In-Class Exercise 3:
What happens if you don't place a value in a variable?
Find out by editing and compiling this program:
In-Class Exercise 4:
Identify the output of this program just by reading
(mental execution).
In-Class Exercise 5:
Identify the output of this program just by reading
A rule: a variable must be declared before it is
used (assigned a value or have a value copied from it).
In-Class Exercise 6:
What is the compiler error you get for this program?
Variations
The following variations are worth knowing:
In-Class Exercise 7:
Consider the following partially-complete program:
Write code where indicated to have the program first
print 6, then 5 (without changing the print statements).
Note writing style:
- A space on either side of the equals sign for assignment.
- The same when you combine declaration and assignment
for a single variable.
- It's customary to remove the space for multiple declarations.
Integer operators
First, let's consider some unary operators:
- These are operators that apply to a single variable.
- For example:
- The unary operators here are the ++ (increment)
and -- (decrement):
- Note writing style: no space between variable and unary operator, but this is also acceptable:
In-Class Exercise 8:
Mentally execute this program - what does it print?
Next, let's examine the familiar binary operators
+, -, *, /
- Addition: +
- Subtraction: -
- Multiplication: *
- Division: /
- Consider this example with addition:
- What happens during execution:
- The values in i and j
are added.
- The resulting value goes into
variable k.
- A long-ish way of saying this aloud:
=>
"k is assigned the sum of the values of
i and j"
- A shorter way:
=>
"k is assigned i plus j"
- Here's an example with multiplication and division:
In-Class Exercise 8:
What does it print?
Expressions and operator-precedence
Consider the following program:
In-Class Exercise 9:
What does it print?
About expressions:
- An expression combines constants (like 1, above), and
variables using operators.
- Example:
i*j - (i+1)*(j-1).
- The above expression is really equivalent to:
(i*j) - ((i+1) * (j-1)).
Here, we added some clarifying parentheses.
- Operator precedence allows us to reduce the
number of clarifying parentheses.
- Java precedence follows standard predence in math:
/, *, +, -.
- The above expression is NOT the same as:
i*j - i+1*j-1.
In-Class Exercise 10:
What does the expression i*j - i+1*j-1
evaluate to when i=7 and j=3?
Problem solving and pseudocode
Suppose we were given the following problem:
write a program to print the first N odd numbers.
We'll solve it in the following steps:
- First, let's sketch out a "program-like" outline (not a real program):
N = 10 // Let's make it work for N=10.
for i=1 to N {
Make the i-th odd number
Print it
}
- This kind of rough outline is called pseudocode
=> We're meant to do this on paper, prior to programming.
- Pseudocode looks a little like code, but is half-English.
- For any given i, the i-th odd number is:
2*i - 1.
- Now let's put this together into a program:
In-Class Exercise 11:
Trace on paper the values of i and k in the
program above. This is what you should be able to do
mentally during mental execution.
More about expressions and assignment
Here are two more operators, one unary (negative sign)
and one binary (remainder or mod operator), that are commonly used:
In-Class Exercise 12:
What does it print?
In-Class Exercise 13:
What does the following program print?
Now we'll look at a strange (initially) but very useful type of
assignment:
- Consider this program:
- Prior to evaluating the expression, i has value 7.
- On the right side, the current value of i is used
to evaluate the expression.
=> Thus, the expression evaluates to (7 + 7/2) = 10.
- This evaluated value then goes into variable i.
=> After the assignment, i has the value 10.
Let's use this to compute the sum of numbers from 0 to 10:
In-Class Exercise 14:
Trace the changing values of s in the above program
using the following table:
More problem-solving examples
Next, we'll look at some well-known ideas from mathematics,
expressed in programs.
The first one is Fibonacci numbers.
- The Fibonacci sequence is this:
0, 1, 1, 2, 3, 5, 8, 13, ...
- Thus, the next Fibonacci number is the sum of the
previous two.
- Fibonacci numbers have proven useful in modeling
biological growth, and have interesting mathematical properties.
- Let's write a program to print Fibonacci numbers.
- Observe: to compute a single Fibonacci number
=> We'll need a variable for it.
- To compute this, we'll need variables for the previous two:
- Let's start with some pseudocode:
N = 10 // We'll go up the N-th Fibonacci #
p = 1 // Initial value of p
q = 0 // Initial value of q
for i=3 to N {
Make the i-th Fibonacci number
Print it
Update p and q
}
- We're going to resist the temptation to code, and instead
refine the pseudocode:
N = 10 // We'll go up the N-th Fibonacci #
p = 1 // Initial value of p
q = 0 // Initial value of q
for i=3 to N {
f = p + q
Print f
q = p
p = f
}
- Now, finally, let's write this up as a Java program:
In-Class Exercise 15:
Trace the changing values of q, p, and f
in the above program using a table.
Next, we'll explore a fascinating and very useful
sequence:
- Consider the sequence
Xn+1 =
aXn mod m
- Here, a and m are integer constants.
- The starting value of the sequence (called the seed)
is X1
In-Class Exercise 16:
Suppose a=7, m=13 and X1=1.
Compute the first few values, up through X4.
- Next, let's write a program to print some of these values.
- We'll begin with pseudocode:
a = 7 // These are the two constants: a, m.
m = 13
x = 1 // Starting value x=1
n = 25 // Print the first 25 values
for i=2 to n {
x = (a*x) mod m
Print x
}
In-Class Exercise 17:
Write a Java program called StrangeSequence
that implements the above idea. The observe the output.
What do you notice? Change a=5 and compare the
output.
- The above type of sequence is the basis for many
random number generators.
- In practical generators, m is usually
very large, e.g., m = 231 - 1
- And a needs to satisfy the property that
is satisfied by a=7 above (which a=5
does not satisfy. Can you guess what this property is?
The third math idea we'll explore: a program to explore a famous
mathematical proof
- This is a well-known formula:
1 + 2 + ... + n = n(n+1)/2
- There is a rather simple proof of this, attributed
to the mathematician Carl Gauss.
- What's interesting: Gauss was reportedly 10 years old
when he discovered this proof.
- The main idea:
- First, write the numbers 1 to n:
- Then, reverse the order and line up the reversed order
underneath:
- Then, add:
- Since the original sum is double-counted here, it must be true
that
1 + 2 + ... + n = n(n+1)/2
- Now, let's explore this in a program:
public class Gauss {
public static void main (String[] argv)
{
int n = 10;
int s = 0; // Use this to accumulate the sum.
int d = 0; // Use this to accumulate the double-sum.
for (int i=1; i<=n; i++) {
int a = i; // The number above.
int b = n-i+1; // The number below.
s = s + i; // Accumulate the sum.
d = d + (a + b); // Accumulate the two terms: (n+1)
}
System.out.println (s); // Print the sum.
System.out.println (d); // Print the double-sum.
int f = n*(n+1)/2;
System.out.println (f); // To verify, print the formula.
}
}
A problem with variables and nested for-loops
We'll solve the following problem:
for any given n, compute
1 + 21 + 22
+ 23 + ... + 2n
That is, the sum of consecutive powers of 2.
As a first step, let's see if we can use a loop to
compute a single power of 2:
- Suppose we wish to compute 2k for some
k.
- We know that
2k
= 2*2*2 ... *2 (k times)
- Thus, what we could is:
Start with p = 1
Multiply by 2: p = p * 2
Multiple that result by 2: p = p * 2
... etc
- In pseudocode:
p = 1
for i=1 to k {
p = p * 2
}
- Let's put this into code and test:
In-Class Exercise 18:
Trace the changing values of p
in the above program using a table. Then, edit, compile
and execute.
- Next, let's look at pseudocode for the sum of powers:
s = 1
for k=1 to n {
Compute k-th power of 2
Accumulate in s
}
Print s
- Now, let's put this all together:
In-Class Exercise 19:
Make a table with columns labeled k, i, p
and s and trace the program, filling
in the table step-by-step.
In-Class Exercise 20:
Try a few other values of n, e.g., n=3
or n=4. Can you guess the mathematical formula for
1 + 21 + 22
+ 23 + ... + 2n?
Choosing variable names
Thus far, for simplicity, we have used short one-letter names
for variables.
It is common to use longer, more meaningful names.
With this in mind, let's demonstrate more appropriate
names by re-writing some earlier programs.
For example, the sum program:
Similarly, here's the Fibonacci program with more
readable variable names.
About variable names:
- They are a matter of taste.
- For programs with obvious mathematical connotation,
it's probably best not to use long names.
- Generally, loop-variable names tend to be short.
Shortcut operators
Recall the integer-sum program:
Here, the line
sum = sum + i;
can be replaced with
sum += i;
The += operator combines assignment and addition.
This can be applied to the other operators as well:
s -= i; // Same as s = s - i;
p *= 2; // Same as p = p * 2;
d /= 2; // Same as d = d / 2;
In-Class Exercise 21:
Rewrite the SumOfPowersOf2 program using
shortcut operators for multiplication and addition.
When things go wrong
As you might imagine, there are many ways to inadvertently
create errors.
Let's start with compilers errors.
In-Class Exercise 22:
Try to identify the compiler error (or errors),
by reading each program below.
Program 1:
Program 2:
Program 3:
Program 4:
Next, let's look at some logical errors.
In-Class Exercise 23:
Consider the sequence of numbers:
1, 2, 6, 42, 1806, 3263442, ....
Here, the n-th term is defined as
Xn = (Xn-1)2 + Xn-1.
Thus, each term is the square of the previous term plus itself.
Here is a program to compute the n-th term:
The program compiles, but has a mistake - can you find it?
In-Class Exercise 24:
What is the error in the program below?
Sometimes an error is not entirely the programmer's
fault but a lack of awareness of language limitations.
For example, consider the power-of-2 program from earlier:
In-Class Exercise 25:
Edit, compile and test the above program. Now set
n=40. What do you observe? What is the largest
possible value of n for which you get a correct
result?