By the end of this module, for simple HelloWorld-like
programs, you will be able to:
Create variable declarations.
Assign values to variables by simple assignment, and print them out.
Distinguish between integers in strings versus actual integers.
Demonstrate ability to perform operations on integers
for a desired output.
Simplify expressions with constants to single value.
Evaluate expressions with variables in them.
Convert English descriptions of operations into expressions.
Mentally trace execution with expressions and calculations.
Mentally trace expressions and calculations inside for-loops.
Produce desired output using for-loops and calculations.
Identify new syntactic elements related to the above.
And, once we've worked with integers, we'll also do some
"number crunching".
5.0 Audio:
First, an analogy
Suppose we have boxes. Consider the following rules about "boxes":
Each box can store only one item.
The possible things that can be stored inside are
called values.
Thus, at any given moment, a box's value is
whatever's inside it.
Each box is "typed"
⇒
What this means:
A box meant for shoes is allowed to store only shoes.
A box meant for caps is allowed to store only caps.
Each box has a unique name:
There is a cloning process that works like
this:
The value inside one box is cloned.
The cloned value is placed inside another.
There is a strange shortcut notation to specify cloning:
Here, the = (equals sign)
does NOT mean "equals."
It has been repurposed to mean
"clone", "copy," or, in programming-language
jargon, "assign".
How to say it: "x is assigned the value in y".
Important: Remember, a box can hold only one value at a time.
5.1 Exercise:
Suppose z is a box that stores caps. What
will the statement z = y result in? Draw a picture.
Integer variables
Consider the following program:
5.2 Exercise:
Edit, compile and execute the above program.
What gets printed out to the terminal?
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".
5.3 Exercise:
What happens if you don't place a value in a variable?
Find out by editing and compiling this program:
5.4 Exercise:
Identify the output of this program just by reading
(mental execution).
5.5 Exercise:
Identify the output of this program just by reading:
Then, write up the program to confirm.
A rule: a variable must be declared before it is
used (assigned a value or have a value copied from it).
5.6 Exercise:
What is the compiler error you get for this program?
5.7 Video:
Variations
The following variations are worth knowing:
Sometimes it's convenient to use comma-separated declarations:
Note: variables need not be declared in the order they are used in the program.
Declaration and assignment can be combined:
Another example:
Remember: a variable can hold only one value at a time.
Note about 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.
Example:
5.8 Exercise:
Consider the following partially-complete program:
Write code where indicated to have the program first
print 6, then 5. You may not change any of the
existing code and you may not directly assign the numbers.
Instead, find a way to swap: that is, whatever is in
i
should go into
j
and whatever is in
j
should go into
i.
5.9 Video:
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):
5.10 Exercise:
Mentally trace what's in the "box" for
i.
Do you see why the second
println.
prints
4
and not
3?
Note writing style: no space between variable and unary operator, but this is also acceptable:
5.11 Exercise:
Mentally execute the program below - what does it print?
5.12 Video:
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:
5.13 Exercise:
Type up this program. What does it print? Change
i to 21.
What is the value of
m?
Integer division:
In math, we learned that 1/4 = 0.25 and 21/6 = 3.5.
In Java, however, the compiler sees that that only
integers are being used, and will perform integer division.
That is, the result is rounded down to the
nearest integer.
Thus, 1/4=0 and 21/6=3.
Later, when we work with real numbers, we will see
that, to compute a real-valued expression, at least one
of the numbers needs to be real-valued.
Example: 1.0/4.0=0.25 or 21.0/6=3.5.
Integer division is useful when we want to do integer
arithmetic.
Expressions and operator-precedence
Consider the following program:
5.14 Exercise:
Type up the above program in
MyExpressionExample.java
(renaming the class name to
MyExpressionExample).
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 precedence in math:
/, *, +, -.
You might remember the precedence via the acronyms
BODMAS or PEMDAS. (Look it up.)
The above expression is NOT the same as:
i*j - i+1*j-1.
5.15 Exercise:
What does the expression i*j - i+1*j-1
evaluate to when i=7 and j=3?
5.16 Video:
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:
5.17 Exercise:
Trace (in module5.pdf)
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:
5.18 Exercise:
What does it print?
One way to know whether one number cleanly divides another
is to apply the
% (remainder)
operator.
5.19 Exercise:
What does the following program print? Write it up in
MyExpressionExample2.java
(renaming the class name to
MyExpressionExample2)
and see.
About the
%
operator:
Examples of its meaning:
10%3 is 1
3%4 is 3
In the above program we see that if j%i is 0 then i divides
j cleanly.
The above program therefore identifies whether a
number smaller than 10 divides it cleanly.
There is at least one, and therefore 10 is not prime.
5.20 Video:
5.21 Exercise:
Write code in
MyExpressionExample3.java
to take the loop in 5.19 above and print the
quotient instead of remainder.
For example, the first three lines of the output should be:
10
5
3
(Thus, for example, when i is 1, the quotient is 10).
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:
5.22 Exercise:
Trace the changing values of s in the above program
using the following table:
Write up the table in
module5.pdf.
Note: in this and other tracing exercises involving a table,
you can simply draw the table by hand and include a picture.
(That is, you don't have to spend time on neatly drawing lines inside
a word editor etc.)
Consider this program:
The program prints the sum of the first N odd numbers.
Recall from earlier that as i goes through 1, 2, 3, ...
(2*i-1) evaluates as successive odd numbers 1, 3, 5, ...
5.23 Exercise:
Trace (in
module5.pdf)
the values of i and
s
in the program above.
Then, edit the code to create an outer loop that varies N from
1 to 10. Do you notice a pattern in the output?
5.24 Video:
More problem-solving examples
Next, we'll look at some well-known patterns in numbers,
which will give us practice with problem-solving.
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.
5.25 Exercise:
Take a short browser break to
read about Fibonacci,
to appreciate his seminal contributions to mathematics.
Let's now 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:
5.26 Exercise:
Trace the changing values of q, p, and f
in the above program using a table.
5.27 Video:
The second "number" 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:
We'll compute the sum in two different ways:
The sum as we've already computed before:
⇒ Remember
s = s + i?
Gauss' method.
We'll use the variable
s
for the first approach.
And
d
for the second approach.
Recall:
d
will have twice the sum.
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 in the row above.
int b = n-i+1; // The number in the row below.
d = d + (a + b); // Accumulate the two terms: (n+1)
s = s + i; // Accumulate the sum in the usual (first) way.
}
System.out.println (s); // Print the sum.
System.out.println (d/2); // Print the double-sum divded by 2.
int f = n*(n+1)/2;
System.out.println (f); // To verify, print the formula.
}
}
5.28 Exercise:
Write the above program in
Gauss.java
and verify.
5.29 Exercise:
Take a short browser break to
read
about Gauss, considered one of the greatest mathematicians
of all time.
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:
5.30 Exercise:
Trace the changing values of p
for the first 10 iterations
in the above program using a table
(in module5.pdf).
Then, edit, compile
and execute.
5.31 Video:
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:
5.32 Exercise:
Make a table with columns labeled k, i, p
and s and trace the program, filling
in the table step-by-step
(in module5.pdf).
5.33 Video:
5.34 Exercise:
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?
(in
module5.pdf)
Hint: add 1 to the sum-of-powers of 2.
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;
5.35 Exercise:
Rewrite the SumOfPowersOf2 program
in SumOfPowersOf2.java
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 by identifying compilers errors by reading carefully.
5.36 Exercise:
Identify the compiler error:
5.37 Exercise:
Identify the compiler error:
5.38 Exercise:
Identify the compiler error:
5.39 Exercise:
Next, let's look at some logical errors.
5.40 Exercise:
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 the
previous term.
Here is a program to compute the n-th term:
The program compiles, but has a mistake - can you find it?
5.41 Exercise:
What is the error in the program below? Write it up to see.
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:
5.42 Exercise:
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?
Meta
Another in our series of occasional "meta" sections that will
step back from the material to comment on how we can learn better.
This was a loooong module with lots of exercises and details.
Let's review:
We introduced the all-important concept of a variable
along with the sense that there's a "place" in the computer
for each variable.
⇒
The "place" is really in the memory (also called RAM) of the computer.
Along with variables is the notion of assignment,
which means "copying the value in one variable into another variable".
Note: assignments are amongst the most common of statements
in everyday code.
When a variable is of a numeric type like integers, we also
need to go over basic operators and show examples.
Further complications arose when the operators have variations.
Since we were on the topic of integers, we took this
opportunity to learn how to do some number-crunching.
When we got to nested loops, it got tricky following the
values of variables through multiple nested loops.
So, if you felt a bit overwhelmed, that's perfectly understandable.
If you have to go back to some of the material to review or try
some exercises again, that's fine. You're going to get better at this!