Spring Semester 2002

Lecture Notes Four: Numbers. Strings. Reading input with ConsoleReader. ConsoleReader revealed.
What's 23? A number. An integer.

Java calls that an int. Most of the times.

What's 3.5? A number with a decimal part.

Java calls that a floating-point number. I see. Isn't there a keyword for that, like int?

There are two of them: double and float. In Java there are two kinds of numbers: integers and floating point numbers.

Integers have no fractional part. Floating point numbers, which have a decimal point and therefore a fractional part.

So 2.0 is a floating-point number ... while 2 is an integer.

The second one does not have any fractional part, while the first one's zero. Not missing, but zero.

In practice this can make a big difference. There are two reasons for having separate types for numbers: one philosophical and one pragmatic.

The philosophy is to use whole numbers when you can't have or don't need a fractional part. It is generally a good idea to choose programming solutions that document one's intentions.

Pragmatically speaking, integers are more efficient than floating-point numbers. They take less storage and are processed faster.

How do you use int, double, float in practice? Like Rectangle they're types.

Unlike objects of type Rectangle numbers are not objects. Yes, Rectangle is a reference type. int, double, float (and 5 other) are primitive types.

So we can declare a variable of type int? Yes. It's like in algebra, except names have types in Java.

In Java each variable has a type. By defining
int a; 
you proclaim that a can hold only integer values.
Even though initialization is optional, it is a good idea always to initialize variables with a specific value.

You should always supply an initial value for every variable at the time you define it. So I could, for example, write:
int a = 3; 

Could you have written
int a = 3.5;
No that is a contradiction in terms. I would have broken my own rule of proclaiming that a won't need a fractional part.

Can we write
double b = 3.4; 
Yes, but how about:
double b = 3;

That would work well, since there's no loss of information. Seeing the missing fractional part of 3 Java will initialize b with 3.0 Symbolic names like a and b are meant to make the program more readable and manageable. Keep in mind, however, that you can only declare and initialize a symbolic name just once in every method.

Why is it good to initialize variables as soon as we define them? So that we don't forget to initialize them at all.

If you try to use an uninitialized variable the compiler will notice and complain. All but the simplest programs use variables to store values. Variables are locations in memory that can hold values of a particular type.

They're called variables because once you store a value in them you can change it later at will. I'd like to see that.

Very well, take a look:
int a = 5;
a = 7;
That prints 7 and it works as follows: a is declared and initialized to 5, but later the value 7 is assigned to it.

Yes, that was an example of an assignment statement. Can I see others?

Yes. Here's a more complicated scenario:
int a = 5;
int b = a + 5; 
This prints 10 as what's being stored in b is the value of a plus 5.

So a symbolic name acts as a storage location (or address) on the left hand side of the equals sign (which is used for assignment statements) ... while when it appears on the right hand side it is replaced by its value.

Can one name appear on both sides of an assignment? Show me an example.

Here's a scenario:
int a = 10; 
a = a + 10; 
By the rule you formulated, that should print 20.

Yes, since the expression on the right is evaluated first, then the resulting value is stored in location named a. What other expressions can we use?

All of arithmetic, if you refer to numbers. However, in general, when you make an assignment of an expression into a variable, the expression on the right, ...

... which can contain method invocations, ... ... is first evaluated, and the resulting value has to be of a compatible type with the type of the variable.

OK, I will try to remember that. Let's work some more examples.

Whys is this legal?
int a = 3; 
double b = a;
Because b becomes 3.0, so we acknowledge the lack of fractional part of a by writing a 0 (zero) for it in b.

Is this legal?
double b = 3.5;
int a = b;
No, because a doesn't have any room for a fractional part (0.5) in it.

Can we just ignore that, the fractional part? You can, but Java won't do that for you unless you specifically request it.

How do I do that? You cast the floating point value to an integer:
double b = 3.5;
int a = (int) b;

This has the effect of discarding the fractional part. What is (int)?

It is the cast to an int operator. It acts like the unary minus sign. For example, the expression
-5 + 3
... which yields -2,

-(5 + 3)
... which yields -8,

... is the same as the difference between
(int)3.6 + 3.6
... which yields 6.6,

... and (int)(3.6 + 3.6), ... which yields 7.

There is a good reason why you must use a cast in Java when you convert a floating point number to an integer: The conversion loses information. You must confirm that you agree to that information loss. Java is quite strict about this. You must use a cast whenever there is the possibility of information loss.

A cast is always of the form
for example (int) or (double).
There are a few methods in class Math that have a related functionality.

evaluates to...

evaluates to...

evaluates to...

Math.round(x) evaluates to the closest integer to x (represented as a long). What's long?

Another kind of integer. We'll talk about it before too long. OK. Hit me with more Math

evaluates to...

evaluates to...

evaluates to...

Math.ceil(x)evaluates to the smallest integer greater or equal to x (as a double). ceil is short for "ceiling". There is also a mathematical "floor" function.

evaluates to...

evaluates to...

evaluates to...

Math.floor evaluates to the largest integer less than or equal to x (as a double). Math is a class that is defined in the java.lang package.

The Math class groups together the definitions of several useful mathematical methods such as: sqrt, pow, sin, cos, exp, log, abs, round, ceil, floor ... and many others. All these methods are static methods (unlike print and println of the System.out object).

Beginners (or uninitiated) might think that in
the round method is applied to an object called Math, because Math. precedes round
... just as System.out. precedes print. That's not true. Math is a class, not an object.

A method such as Math.round that does not operate on any object is known as a static method; another example is main. Static methods do not operate on objects, but they are still defined inside classes, and you must specify the class to which the round method belongs.

How can you tell whether Math is a class or an object. You really can't.

Then how do we know? It is certainly useful to memorize the names of the more important classes (such as System and Math). You should also pay attention to capitalization.

All classes in the Java library start with an uppercase letter (such as System). Objects and methods start with a lowercase letter (such as out and println).

You can tell objects and methods apart because method calls are followed by parentheses. Therefore
denotes a call of the println method on the out object inside the System class. On the other hand
denotes a call to the round method...

... inside the Math class. This use of upper- and lowercase letters is merely a convention, not a rule of the Java language. It is, however, a convention that the authors of the Java class libraries follow consistently. You should do the same in your programs.

You can use all four basic arithmetic operations in Java: addition, subtraction, multiplication, and division. Parentheses are used just as in algebra: to indicate in which order the subexpressions should be computed.

Just as in regular algebraic notation, multiplication and division bind more strongly than addition and subtraction. So
3 + 5 * 2 yields 13
(3 + 5) * 2 yields 16
as the parentheses come into play.

Division works as you would expect, as long as at least one of the numbers involved is a floating-point number. However, if both numbers are integers, then the result of the division is always an integer, with the remainder discarded.

Here are some examples: ... evaluates to:

17 / 4 4

10 / 3 3

13 / 7 1

and 6 / 9 evaluates to... 0

If you're interested only in the remainder, you can use the % operator: ... evaluates to:

17 % 4 1

10 % 3 1

13 % 7 6

and 6 % 9 evaluates to... 6

The symbol % has no analog in algebra. It was chosen because it looks similar to /, and the remainder operation is related to division.
Is it true that...
(a / b) * b + a % b
... is the same as a for a and b positive integers?

Yes, but can you prove it? OK, let's move on.

What is
16 / 5 * 5
15, since all operands are integers.

How about
(16 / 5) * 5
Still 15, and in the same way.

What then is
5 * (16 / 5)
15 (multiplication is commutative).

OK, drop the parentheses:
5 * 16 / 5
The result is now 16 as we have to do the multiplication first.

What property requires this? Left-to-right associativity.

Very good. Let's move on.

Next to numbers strings are the most important data type that most programs use. A string is a sequence of characters, such as "Hello" In Java strings are enclosed in quotation marks, which are not themselves part of the string.

You can declare variables that hold strings:
String name = "John"; 
Use assignment to place a different string into the variable:
name = "Carl"; 

The number of characters in a string is called the length. For example, the length of "Hello!" is 6. You can compute the length of a string with the length method:
int n = name.length(); 

That would place 4 in n. For our example, yes.

By the way, a string of length 0 (zero), containing no characters, is called the empty string ... and is written as "".

Also note that unlike numbers, strings are objects. Rectangles were objects too. You can tell that String is a class because it starts with an uppercase letter. The basic types int and double start with a lowercase letter.

Once you have a string, what can you do with it? You can extract substrings, and you can glue smaller strings together to form larger ones.

To extract a string use the substring operation.
s.substring(start, pastEnd)
returns a string that is made up
... from the characters in the string s starting at character with index start, and containing all characters up to, but not including the character with index pastEnd. Let's see an example.

String a = "automaton"; 
String b = a.substring(2, 8); 
// b is set to "tomato"
In Java there are two ways of writing comments.

We already know (and have used it above) that the compiler ignores anything that you type between // and the end of line. The compiler also ignores any text between a /* and */. The // comment is easier to type if the comment is only a single line long.

If you have a comment that is longer than a line or two, then the /* ... */ comment is simpler.
So we could also have:
String c = "appearance";
String d = c.substring(2, 6); 
/* d is "pear" as the substring operation 
  makes a string that consistsd of four
  characters taken from string c */ 

A curious aspect of the substring operation is the numbering of starting and ending positions. Starting position 0 (zero) means "start at the beginning of the string".

For technical reasons that used to be important but are no longer relevant, Java string position numbers start at 0 (zero). The first position is labeled 0 (zero), the second one is labeled 1 (one), and so on.

For example here are the position numbers in the "appearance" string: The position number of the last character (a for the "appearance" string) is always 1 less than the length of the string.

How do you extract the substring "Bird" from
"Larry Bird, Indiana"
           1       1
Count characters starting at 0, not 1. You find that B, the 7th character, has position number 6. The first character that you don't want, a comma, is the character at position 10.

Therefore the appropriate substring command is
String m = "Larry Bird, Indiana";
String n = m.substring(6, 10); 
It is curious that you must specify the position of the first character that you do want and then the first character that you don't want.

There is one advantage to this setup. You can easily compute the length of the substring: it is
pastEnd - start
If you omit the second parameter of the substring method, then all characters from the starting position to the end of the string are copied.

For example:
String u = "Larry Bird, Indiana";
String tail = u.substring(6);
... sets tail to the string
"Bird, Indiana"

This is equivalent to the call I see.
String tail = u.substring(6, u.length());

Now that you know how to take strings apart, let us see how to put them back together. Given two strings, such as "India" and "napolis", you can concatenate them to one long string.
String one = "India"; 
String two = "napolis"; 
String city = one + two; 

The + operator concatenates two strings. How do you get "Larry Bird" out of "Larry" and "Bird"?

"Larry" + " " + "Bird"
Very good, with a blank in the middle.

The concatenation operator in Java is very powerful. If one of the expressions, either to the left or the right of a + operator, is a string, then the other one is automatically forced to become a string as well, and both strings are concatenated.

For example: ... evaluates to:

"Agent" + 7

"2" + 3

2 + 3

Of course when associativity comes into play you have to be a bit more careful. ... evaluates to:

2 + "" + 3

whereas... ... evaluates to:

2 + 3 + ""

Concatenation is very useful to reduce the number of System.out.print instructions. Fine. What if you want to convert a string like "23" that contains only decimals into a number?

To convert a string into a number you have two possibilities: to convert to an int use

... and to convert to a double use

So, ... ...evaluates to:

"23" + 5

Integer.parseInt("23") + 5

"2.3" + 5

Double.parseDouble("2.3") + 5

How can you get a "2.3" string when you need a number? If you're a user and type a number such as 2.3 you will realize that you, in fact, have to type three characters:

... the digit 2, the period, and the digit 3. The whole thing is a string of characters.

And that's what you will have to start from when dealing with user input. How can we write programs that accept user input?

We will use a non-standard Java class, that we will thoroughly discuss later on, and whose purpose is to make processing keyboard input easier and less tedious. We recommend that you use the ConsoleReader class in your own programs whenever you need to read console input.

Simply place the ConsoleReader.java file together with your program file, into a common directory. The purpose of the ConsoleReader class is to add a friendly interface to an input stream such as System.in and her's how you use it.

To accept user input in a program you first need to construct a ConsoleReader object, like this:
ConsoleReader console = new ConsoleReader(System.in);
Next, simply call one of the following three methods:
String line = console.readLine(); // read a line of input 
int n = console.readInt();        // read an integer 
double x = console.readDouble();  // read a floating-point number 

Let's see an example. OK, let's write a program that asks a user for a name (that will be recorded as a String), an amount of dollars (that the user has) and the rate of exchange between the British pound and the American dollar.

The program asks all this of the user, and then computes and tells the user how many British pounds the user would get in exchange for the amount of dollars the user has. Why not leave this for tomorrow?

Good idea. See you in the lab.

Last updated: Jan 9, 2002 by Adrian German for A201