CSCI 201 -- Numbers and Expressions

This lab will introduce you to how Java programs work with numbers and expressions.

Binary Numbers

The range of numbers in Java

As you should know from your reading, numbers in Java come in six different categories which differ in range and precision. But just in case you can't remember the details, here's a little table to help you out.

TypeWhat it can hold
byteHolds a whole number from -128 to 127.
shortHolds 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 a whole number 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.

Testing out the range

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 displayed numbers. For example, when you press the * 10 button, the numbers are multiplied by 10. Actually all six numbers should be the same, but as they multiplied by ten they will start to differ. Some will "lose" high digits due to overflow, and others will "lose" low digits due to lack of precision.

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.

Raw bits

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 some 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.

To convert decimal to binary by division

A decimal number can be converted 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).

Twos Complement Notation

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
1
-1
43
-43
96
-96
127
-127
-128

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 2008 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 button presses that change 2008 to 1492. However, we suggest you just keep reading.

Making some Java expressions

Your Assignment

Start up DrJava (which you can now do through the menu). Next go to the Interactions span and make the following four initializing declarations.

int i    =  201 ;
int j    = 2008 ;
double y = 3.75 ;
double z = 2e22 ;

Now we want you to enter Java expressions in the Interactions panel that compute the following mathematical expressions. Your expressions must use the variables i, j, y, and z. You can't just pull out your calculator, figure out the answer, and type it in.

  1. j + y
  2. j y
  3. Average of y and z
  4. Average of i and j as a decimal number
  5. The remainder when j is divided by i
  6. y (i + j)
  7. y i + j
  8. (y + z) / (y - z)
  9. i / (i + j)
  10. (i + j) / i
  11. The whole part of y
  12. The fractional (decimal) part of y
  13. y rounded to the nearest integer
  14. The last digit of i
  15. i, but with its last digit replaced by 3
  16. π z2
  17. y2 + 4 j z
  18. - z3
  19. 2i/12.0
  20. That interesting problem your lab instructor writes on the board

Some big hints

Multiplication

Mathematicians often write multiplication as “j y”, that is, without an explicit multiplication sign. Programmers need to write “j * y” in this case.

Exponentiation

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 to a non-integral power, Java has a method called Math.pow. For example, y0.5 could be computed in Java as Math.pow(y, 0.5). If you have more questions, ask your instructor how to use it. This is one of the many things you'll learn in the lab rather than the lecture.

Transforming decimal numbers to integers

Java's ugly cast operation, as in “(int) y”, should be used to transform a double into the appropriate int.

π (pi)

Math.PI is Java's easy way of making pi.

Show your expressions to the lab instructor. Better yet, after completing each set of five, show those five to your instructor.