Module 5: Integers


Objectives

 

By the end of this module, for simple HelloWorld-like programs, you will be able to:

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":

 

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:
      1. The sum as we've already computed before:
               ⇒ Remember s = s + i?
      2. 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!
 

5.43 Audio:



© 2017, Rahul Simha