This lab will introduce you to how Java programs work with numbers and expressions.
As you should know from your reading, numbers in Java come in six different categories which differ in range and precision. But just in can you can't remember the details, here's a little table to help you out.
Type | What it can hold |
---|---|
byte | Holds a whole number from -128 to 127. |
short | Holds a whole number from -32,768 to 32,767. |
int | Holds a whole number from -2,147,483,648 to 2,147,483,647. |
long | Holds an whole integer from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. |
float | Holds a decimal number with a range of about -1038 to 1038 and a precision of about seven decimal digits. |
double | Holds a decimal number with a range of about -10308 to 10308 and a precision of about fifteen decimal digits. |
In the table below, you see four range testers written as a Java applet. The five buttons for these applets can be used to modify the displayed numbers. For example, when you press the * 10 button, the number is multiplied by 10. The number is stored in six different ways. Originally all six numbers are the same, but with additions and multiplications the numbers will start to differ.
Below each tester is a short little exercise we'd like you to try out. Read the description with each exercise to increase your understanding of the limitations of computer arithmetic.
Try to set this number to 1000 (103).
Notice that the
byte
has already exceeded its maximum capacity. It is now displaying a negative
number very different from 1000. |
|
Try to set this one to 1000000050 (109+50).
Notice that the
byte
and short have been long exhausted. However, there's
something interesting about the float . Although a
float can hold a number as large as 1038,
it can only hold seven significant decimal places. So, it
can't distinguish between 1000000000 and 1000000050. |
|
Try to set this one to 1000000000000000050 (1018+50).
This number is near the top of the range for a
long .
Notice that the double can't hold this precise value. |
|
Patiently go up 1040. Everything but the
double
is in trouble. The float even holds a special value
corresponding to positive infinity. |
|
Show the instructor your numbers.
Programmers need to understand a bit about how different data types are stored in the computer. Here we are going to look at how integers are stored in the computer. We've written a Java applet to give you a little practice in converting decimal numbers to their binary representations.
In the table below, you'll see some decimal numbers in the left hand side. These are your targets. In the middle of the table, you see a row of black and red dots. These represent bits or binary numbers. Red means binary 1. Black means binary 0. Go ahead and mash one of the dots. It changes state -- 0 becomes 1, 1 becomes 0. Notice that the rightmost number also changes. It is the decimal number corresponding to the binary number.
Your job is to set the binary bits so that the right column matches the left column, if possible. This can be a little tricky for negative numbers as they are encoded in twos complement notation as required by the Java virtual machine specification. In this case, first find the positive number number that is one less than the absolute value of the negative number and then reverse all the bits. For example, if the goal is to find -127, first find 126 and then reverse all the bits.
A decimal number can be convered to a binary number by repeated dividing by two and recording the remainder (0 or 1) of that division each time.
Starting with decimal number 90:
Operation | Quotient | Remainder |
---|---|---|
90 / 2 | 45 | 0 |
45 / 2 | 22 | 1 |
22 / 2 | 11 | 0 |
11 / 2 | 5 | 1 |
5 / 2 | 2 | 1 |
2 / 2 | 1 | 0 |
1 / 2 | 0 | 1 |
The binary equivalent reads from the bottom up in the remainder column. Thus 90 (decimal) = 1011010 (binary).
The above section applies to positive number. (In fact, you can apply it to negative numbers in Java, but you must consider -5 / 2 to be -3. Although this result makes many mathematicians happy, most ordinary folks find it disagreeable.)
The Java standard states that integers are to be stored in twos complement notation. To change the sign of binary integer in twos complement notation, you must first invert the bits, that is, convert 0's to 1's and 1's to 0's. Then you add 1 to the inverted result.
For example, suppose you want to conversion -90 to a 16-bit
(Java short
) integer.
First, convert 90 to a binary number as described above.
This will give you 1011010. However, that's only seven bits, so
you must stick another nine 0's on the front to get sixteen bits.
Now you have 0000000001011010.
Invert the sixteen bits to get 1111111110100101.
Finally add in a one. That's your final answer
1111111110100110.
Start off with eight bit numbers. These correspond to the
Java byte
type.
By the way, at least one of these examples is outside the
allowed range for Java byte
values.
Target | Your guess |
---|---|
20 | |
43 | |
66 | |
99 | |
127 | |
128 |
Now try out binary representations using 16 bits.
These correspond to Java short
integers.
Target | Your guess |
---|---|
128 | |
201 | |
-201 | |
32767 | |
-32768 | |
-1 |
Ask your lab instructor to verify that you've pushed all the right buttons.
But what about floating point? Well, that's harder.
Below you see the bits of 2006 as a 32-bit floating point number,
Java's float
type.
The three fields of the number are:
(1), sign, in light red; (2), exponent, in light green;
and (3), fraction, in light blue.
If you press the left-most button in the display, you
change the sign of the number.
If you press the right-most button, which is the last bit of
the fraction,
you make a tiny change to the number.
If you press buttons toward the left end of the fraction (blue) zone,
you'll see larger changes.
If you press buttons in the exponent (green) zone, there will be
some big changes.
If you are adventurous, you can try to find the two button presses that change 2006 to 1492.
Java executes expressions according to the order of operations you learned in high school algebra. We hope you know this by heart, but if you've forgotten, just remember that expressions inside of parenthesis are evaluated first, and that the operators multiplication, division and remainder are evaluated before the operators addition and subtraction.
An expression contains operators that must be evaluated.
Usually expressions appear in assignment statements of the form:
Variable = Expression
In such statements, the expression is
evaluated and the result of the evaluation is then
assigned to the variable. This process is illustrated in the
following Stack N' Heap simulation.
This simulation allows you to step through the Java code
by pressing the double greater-than signs (>>) is the
"Code" box.
Begin by using the following link to download a ZIP file called Expr.zip. Then extract the directory Expr into your csci/201 directory.
Next start up NetBeans and open the project you now have stored in your csci/201/Expr directory.
If you do not remember how to do this, you may go back to the downloading projects lab. Your lab instructor may be willing to help you with the extraction this week, but by next week this activity needs to be on auto-pilot.
You must make your Projects panel look
something like the following picture before continuing. If you are having
trouble obtaining this layout, call your instructor (or a fellow student) now.
Study, build, and run the Main
class of the
expr
package.
Presently, this program uses a random number generator
(edu.unca.cs.labaids.TestValues
)
to generate four numbers, two integers i
and j
and two double-precision floating point numbers
y
and z
and then has sixteen very incomplete statements for
printing the value of an expression.
Your job is to modify the main
method to print
all of the
sixteen expressions listed in the table below.
Notice that the first expression is already done for you.
To verify if you answers are correct, you should copy the
"solution set" number as displayed by your running program
into the
Solution Set Number
field of the Java applet running below on the right.
For example, if you run your program and the first line
is
Running solution set 21
then you should type 21 into the
Solution Set Number field
to see the correct solution.
You should run your program two or three times to make sure it agrees with the solution set numbers before asking the instructor to check-off this lab.
Expression Number |
Expression | |
---|---|---|
0 | Average of y and z |
|
1 | Average of i and j |
|
2 | The remainder when i is
divided by j |
|
3 | y
(i + j) |
|
4 | y
i + j |
|
5 | (y + z)
/ (y - z) |
|
6 | i / (i + j) |
|
7 | (i + j) / i |
|
8 | The whole part of y | |
9 | The fractional (decimal) part of y | |
10 | The last digit of i |
|
11 | i , but with its last digit replaced by 3 |
|
12 | π z 2 |
|
13 | y2 +
4 j z |
|
14 | - z3 |
|
15 | iy
Hint: Use the pow method of the Math class.
|
Exponentiation is the operator where a number is multiplied
by itself several times. For example,
y3 is y*y*y.
Java does not have a "built-in" exponentiation operator
like the **
operator of FORTRAN.
For exponentiation to a small power, just use the *
operation two or three times. For exponentation to a large power,
or even a non-integral power, Java has a method called
Math.pow
. Ask
your instructor how to use it. I suspect that methods have
not yet been discussed in class.
Math.PI
is Java's easy way of making pi.
After you have thoroughly tested your code, and you understand why the expressions print as they do, ask your instructor to test your code.