Due: Friday, 14 October 2005 by 10 a.m.
In this homework, you will implement a few exercises on integers in order to gain more experience using Java control structures, such as for loops, while loops, and if-else statements. In the process you will deal with some very large numbers, so you will also use the BigInteger class that Java provides to manipulate very large integers. The BigInteger class is in the java.math library, so you will have to have the following line at the top of your program:
Your code should be in a NumberGames class in a file named NumberGames.java.
This assignment is longer than the previous assignments. The best way to tackle it is to do one part at a time, and test that part. Once it works, move on to the next part.
An int can only represent a certain range of numbers, approximately -2 billion to +2 billion. The Java primitive variable type long can represent a larger, but still finite, range. Java's BigInteger class supports integers of unlimited size, though arithmetic operations on BigIntegers can be significantly slower than on int and long. For this assignment you will use the BigInteger class to store the very large numbers which can result from the Fibonacci, primality, and exponentiation computations described above. In particular, we are going to be testing your code with values that are larger than a long can hold, so you will have to use BigInteger.
For example, the following code creates two BigIntegers, and adds them together to create a third BigInteger.
BigInteger bignum1 = new BigInteger ("234238947239487");
BigInteger bignum2 = new BigInteger ("12349871239487123984");
BigInteger bignum3 = bignum1.add(bignum2);
Note that unlike a StringBuffer, each BigInteger method call creates a new BigInteger -- it does not modify the existing one.
In this assignment you have the user input a number (let's call it i), then calculate and print the ith Fibonacci number, the number 2i, all all the prime numbers less than i. Note that if you enter a very large value of i (say, 100), then your program will take a very long time (especially the prime number part). Thus, experiment with smaller values of i until you know your program is working.
The ith Fibonacci number is defined as the sum of the previous two Fibonacci numbers. The first and second Fibonnaci numbers are always defined as 1 and 1. In other words, each Fibonacci number is equal to the sum of the two before it in the sequence, with the first two numbers starting the sequence at 1. Thus the first few terms of the Fibonacci sequence are:
1 1 2 3 5 8 13 21 34 55 ...
because 1+1=2, 1+2=3, 2+3=5, 3+5=8, and so on. Let f(n) be the nth Fibonacci number. Thus, f(1) is 1, f(2) is 1, f(3) is 2, f(10) is 55, etc. The formal definition for the Fibonacci sequence is:
f(1) = 1
f(2) = 1
f(n) = f(n-1) + f(n-2) when n > 2
This will require a while or for loop, where each iteration of the loop computes the next term of the sequence. Because the Fibonacci numbers get large very quickly, you will have to use the BigInteger class to hold the numbers. Once your program has computed ith Fibonacci number, it should be printed out to the screen.
You are welcome to print out all the Fibonacci numbers as they are computed. However, at the end of that, you need to print out something along the lines of, "the 10th Fibonacci number is 55".
For this part of the assignment, you will use the same value for i, and compute the exact integer value of 2i. Java provides routines for exponentiation, but they are based on floating point arithmetic and logarithms; if i is large enough, the ith power of two cannot be calculated exactly using these routines nor represented exactly using floating point arithmetic. Instead, you will simply use a single loop to iteratively multiply 2 a total of i times. Again, this should be represented by BigIntegers. The computed number should be printed out to the screen.
You are welcome to print out all the powers of 2 as they are computed. However, at the end of that, you need to print out something along the lines of, "the 10th power of 2 is 1024". You may not use the pow() method in the BigInteger class.
Note that 1 is not a prime number! (really) Thus, the first prime number is 2.
For this part of this assignment, you will use the same number i already input by the user, and print out all the prime numbers less than or equal to i. Note that this is different from printing out the ith prime number. For example, if the user enters 6, you should print out all the prime numbers less than or equal to 6 (2, 3, 5), and not the 6th prime number (13, as the prime numbers go 2, 3, 5, 7, 11, 13).
Because prime numbers do not increase very rapidly (compared with the other parts), you should use int variables for this part. You will notice that BigInteger class (described above) provides some methods for finding primes: isProbablePrime(), nextProbablePrime(), and probablePrime(). Needless to say, you are not allowed to use these methods, or any code based on these methods.
To test whether a number n is prime, you will need to use nested for or while loops. For each number n that you are testing for primality (those numbers range from 2 to i), you need to test all numbers (we'll call them j) from 2 to n-1 to see if any of them divide n evenly (remember the modulus operator: %). The loop for the numbers n form the outer nested loop, and the loop for the numbers j forms the inner nested loop. In the process you may wish to use a boolean variable to indicate whether the computation has yet found a value of j which evenly divides n. For example, such a variable might called "foundFactor" and initialized to false at the beginning of each primality test. A boolean variable used this way is often called a flag.
This last part deals with measuring the speed of the computations of the above parts. The System class provides a method to get the current time: System.currentTimeMillis(). This method returns a long, which is the total number of milliseconds since January 1, 1970. Thus, the numbers returned by it are going to be rather large. You can get the current time (number of milliseconds) by the following code:
long currentTime = System.currentTimeMillis();
You need to store the current time before each of the three parts described above, and then once the computation is done, determine (based on the initial time that was stored and the current time through another call to System.currentTimeMillis()) how long the computation took. The total number of milliseconds taken for each of the three parts described above should be printed out to the screen.
The good programming practices from HW J1 need to be in this homework as well.
We are not providing a sample execution for this program. However, in order to test your program, you may wish to know the following:
You may assume that we will not test it with any value of i less than 5. This may make your code simpler, since you will not have to handle special cases such as i=1 and i=2.
This program will require loops, including nested loops. For some computations a while loop will probably feel more natural, while for others a for loop will probably be more straightforward to code. You can use whatever you prefer. Remember to consider all the loop constructs that Java provides when coding this assignment.
Although we will not provide a sample execution, we will provide what the values should be.
For i=100 (this may take a very long time)
When you are finished, submit the NumberGames.java file.