Chapter 8

Numbers? Who Needs Numbers?

IN THIS CHAPTER

check Working with characters

check Dealing with “true” or “false” values

check Rounding out your knowledge of Java’s primitive types

I don’t particularly like fax machines. They’re so inefficient. Send a short fax, and what do you have? You have two slices of a tree — one at the sending end and another at the receiving end. You also have millions of dots — dots that scan tiny little lines across the printed page. The dots distinguish patches of light from patches of darkness. What a waste!

Compare a fax with an email message. Using email, I can send a 25-word contest entry with just 2,500 zeros and ones, and I don’t waste any paper. Best of all, an email message doesn’t describe light dots and dark dots. An email message contains codes for each of the letters — a short sequence of zeros and ones for the letter A, a different sequence of zeros and ones for the letter B, and so on. What could be simpler?

Now imagine sending a one-word fax. The word is true, which is understood to mean, “True, I accept your offer to write Beginning Programming with Java For Dummies, 5th Edition.” A fax with this message sends a picture of the four letters t-r-u-e, with fuzzy lines where dirt gets on the paper and little white dots where the cartridge runs short on toner.

But really, what’s the essence of the “true” message? There are just two possibilities, aren’t there? The message could be “true” or “false,” and to represent those possibilities, I need very little fanfare. How about 0 for “false” and 1 for “true?”

  • They ask, “Do you accept our offer to write Beginning Programming with Java For Dummies, 5th Edition?”

    “1,” I reply.

Too bad I didn’t think of that a few months ago. Anyway, this chapter deals with letters, truth, falsehood, and other such things.

Characters

In Chapters 6 and 7, you store numbers in all your variables. That’s fine, but there’s more to life than numbers. For example, I wrote this book with a computer, and this book contains thousands and thousands of nonnumeric things called characters.

The Java type that’s used to store characters is char. Listing 8-1 has a simple program that uses the char type, and a run of the Listing 8-1 program is shown in Figure 8-1.

image

FIGURE 8-1: Exciting program output!

LISTING 8-1 Using the char Type

class LowerToUpper {

public static void main(String args[]) {
char smallLetter, bigLetter;

smallLetter = ’b’;
bigLetter = Character.toUpperCase(smallLetter);
System.out.println(bigLetter);
}
}

In Listing 8-1, the first assignment statement stores the letter b in the smallLetter variable. In that statement, notice how b is surrounded by single quote marks (’ ’). In a Java program, every char literal starts and ends with a single quote mark.

technicalstuff When you surround a letter with quote marks, you tell the computer that the letter isn’t a variable name. For example, in Listing 8-1, the incorrect statement smallLetter = b would tell the computer to look for a variable named b. Because there’s no variable named b, you’d get a b cannot be resolved to a variable message.

In the second assignment statement of Listing 8-1, the program calls an API method whose name is Character.toUpperCase. The method Character.toUpperCase does what its name suggests — the method produces the uppercase equivalent of a lowercase letter. In Listing 8-1, this uppercase equivalent (the letter B) is assigned to the variable bigLetter, and the B that’s in bigLetter is printed on the screen, as illustrated in Figure 8-2.

image

FIGURE 8-2: The action in Listing 8-1.

remember When the computer displays a char value on the screen, the computer doesn’t surround the character with single quote marks.

I digress …

A while ago, I wondered what would happen if I called the Character.toUpperCase method and fed the method a character that isn’t lowercase to begin with. I yanked out the Java API documentation, but I found no useful information. The documentation said that toUpperCase “converts the character argument to uppercase using case mapping information from the UnicodeData file.” Thanks, but that’s not useful to me.

Silly as it seems, I asked myself what I’d do if I were the toUpperCase method. What would I say if someone handed me a capital R and told me to capitalize that letter? I’d say, “Take back your stinking capital R.” In the lingo of computing, I’d send that person an error message. So I wondered whether I’d get an error message if I applied Character.toUpperCase to the letter R.

I tried it. I cooked up the experiment in Listing 8-2.

LISTING 8-2 Investigating the Behavior of toUpperCase

class MyExperiment {

public static void main(String args[]) {
char smallLetter, bigLetter;

smallLetter = ’R’;
bigLetter = Character.toUpperCase(smallLetter);
System.out.println(bigLetter);

smallLetter = ’3’;
bigLetter = Character.toUpperCase(smallLetter);
System.out.println(bigLetter);
}
}

In my experiment, I didn’t mix chemicals and blow things up. Here’s what I did instead:

  • I assigned ’R’ to smallLetter.

    The toUpperCase method took the uppercase R and gave me back another uppercase R. (See Figure 8-3.) I got no error message. This told me what the toUpperCase method does with a letter that’s already uppercase. The method does nothing.

  • I assigned ’3’ to smallLetter.

    The toUpperCase method took the digit 3 and gave me back the same digit 3. (See Figure 8-3.) I got no error message. This told me what the toUpperCase method does with a character that’s not a letter. It does nothing — zip, zilch, bupkis.

image

FIGURE 8-3: Running the code in Listing 8-2.

I write about this experiment to make an important point. When you don’t understand something about computer programming, it often helps to write a test program. Make up an experiment and see how the computer responds.

I guessed that handing a capital R to the toUpperCase method would give me an error message, but I was wrong. See? The answers to questions aren’t handed down from heaven. The people who created the Java API made decisions. They made some obvious choices, and they also made some unexpected choices. No one knows everything about Java’s features, so don’t expect to cram all the answers into your head.

The Java documentation is great, but for every question that the documentation answers, it ignores three other questions. So be bold. Don’t be afraid to tinker. Write lots of short, experimental programs. You can’t break the computer, so play tough with it. Your inquisitive spirit will always pay off.

Reading and understanding Java’s API documentation is an art, not a science. For advice on making the most of these docs, read my article “Making Sense of Java’s API Documentation,” at www.dummies.com/programming/java/making-sense-of-javas-api-documentation.

One character only, please

A char variable stores only one character. So if you’re tempted to write the following statements

char smallLetters;
smallLetters = ’barry’; //Don’t do this

please resist the temptation. You can’t store more than one letter at a time in a char variable, and you can’t put more than one letter between a pair of single quotes. If you’re trying to store words or sentences (not just single letters), then you need to use something called a String. For a look at Java’s String type, see Chapter 18.

Variables and recycling

In Listing 8-2, I use smallLetter twice, and I use bigLetter twice. That’s why they call these things variables. First, the value of smallLetter is R. Later, I vary the value of smallLetter so that the value of smallLetter becomes 3.

When I assign a new value to smallLetter, the old value of smallLetter gets obliterated. For example, in Figure 8-4, the second smallLetter assignment puts 3 into smallLetter. When the computer executes this second assignment statement, the old value R is gone.

image

FIGURE 8-4: Varying the value of smallLetter.

Is that okay? Can you afford to forget the value that smallLetter once had? Yes, in Listing 8-2, it’s okay. After you’ve assigned a value to bigLetter with the statement

bigLetter = Character.toUpperCase(smallLetter);

you can forget all about the existing smallLetter value. You don’t need to do this:

// This code is cumbersome.
// The extra variables are unnecessary.
char smallLetter1, bigLetter1;
char smallLetter2, bigLetter2;

smallLetter1 = ’R’;
bigLetter1 = Character.toUpperCase(smallLetter1);
System.out.println(bigLetter1);

smallLetter2 = ’3’;
bigLetter2 = Character.toUpperCase(smallLetter2);
System.out.println(bigLetter2);

You don’t need to store the old and new values in separate variables. Instead, you can reuse the variables smallLetter and bigLetter as in Listing 8-2.

This reuse of variables doesn’t save you from a lot of extra typing. It doesn’t save much memory space, either. But reusing variables keeps the program uncluttered. When you look at Listing 8-2, you can see at a glance that the code has two parts, and you see that both parts do roughly the same thing.

The code in Listing 8-2 is simple and manageable. In such a small program, simplicity and manageability don’t matter much. But in a large program, it helps to think carefully about the use of each variable.

When not to reuse a variable

The previous section discusses the reuse of variables to make a program slick and easy to read. This section shows you the flip side. In this section, the problem at hand forces you to create new variables.

Suppose that you’re writing code to reverse the letters in a four-letter word. You store each letter in its own, separate variable. Listing 8-3 shows the code, and Figure 8-5 shows the code in action.

image

FIGURE 8-5: Stop those pots!

LISTING 8-3 Making a Word Go Backward

import java.util.Scanner;

class ReverseWord {

public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
char c1, c2, c3, c4;

c1 = keyboard.findWithinHorizon(".", 0).charAt(0);
c2 = keyboard.findWithinHorizon(".", 0).charAt(0);
c3 = keyboard.findWithinHorizon(".", 0).charAt(0);
c4 = keyboard.findWithinHorizon(".", 0).charAt(0);

System.out.print(c4);
System.out.print(c3);
System.out.print(c2);
System.out.print(c1);
System.out.println();

keyboard.close();
}
}

The trick in Listing 8-3 is as follows:

  • Assign values to variables c1, c2, c3, and c4 in that order.
  • Display these variables’ values on the screen in reverse order: c4, c3, c2, and then c1, as illustrated in Figure 8-6.
image

FIGURE 8-6: Using four variables.

If you don’t use four separate variables, you don’t get the result that you want. For example, imagine that you store characters in only one variable. You run the program and type the word pots. When it’s time to display the word in reverse, the computer remembers the final s in the word pots. But the computer doesn’t remember the p, the o, or the t, as shown in Figure 8-7.

image

FIGURE 8-7: Getting things wrong because you used only one variable.

I wish I could give you 12 simple rules to help you decide when and when not to reuse variables. The problem is, I can’t. It all depends on what you’re trying to accomplish. So, how do you figure out on your own when and when not to reuse variables? Like the guy says to the fellow who asks how to get to Carnegie Hall, “Practice, practice, practice.”

Reading characters

The people who created Java’s Scanner class didn’t create a next method for reading a single character. So, to input a single character, I paste two Java API methods together. I use the findWithinHorizon and charAt methods.

Table 5-1 (over in Chapter 5) introduces this findWithinHorizon(".", 0).charAt(0) technique for reading a single input character, and Listing 8-3 uses the technique to read one character at a time. (In fact, Listing 8-3 uses the technique four times to read four individual characters.)

Notice the format for the input in Figure 8-5. To enter the characters in the word pots, I type four letters, one after another, with no blank spaces between the letters and no quote marks. The findWithinHorizon(".", 0).charAt(0) technique works that way, but don’t blame me or my technique. Other developers’ character-reading methods work the same way. No matter whose methods you use, reading a character differs from reading a number. Here’s how:

  • With methods like nextDouble and nextInt, you type blank spaces between numbers.

    If I type 80 6, then two calls to nextInt read the number 80, followed by the number 6. If I type 806, then a single call to nextInt reads the number 806 (eight hundred six), as illustrated in Figure 8-8.

  • With findWithinHorizon(".", 0).charAt(0), you don’t type blank spaces between characters.

    If I type po, then two successive calls to findWithinHorizon(".", 0).charAt(0) read the letter p, followed by the letter o. If I type p o, then two calls to findWithinHorizon(".", 0).charAt(0) read the letter p, followed by a blank space character. (Yes, the blank space is a character!) Again, see Figure 8-8.

image

FIGURE 8-8: Reading numbers and characters.

remember To represent a lone character in the text of a computer program, you surround the character with single quote marks. But, when you type a character as part of a program’s input, you don’t surround the character with quote marks.

warning Suppose that your program calls nextInt and then findWithinHorizon(".", 0).charAt(0). If you type 80x on the keyboard, you get an error message. (The message says InputMismatchException. The nextInt method expects you to type a blank space after each int value.) Now what happens if, instead of typing 80x, you type 80 x on the keyboard? Then the program gets 80 for the int value, followed by a blank space for the character value. For the program to get the x, the program has to call findWithinHorizon(".", 0).charAt(0) one more time. It seems wasteful, but it makes sense in the long run.

WHAT’S IN A NAME?

tryitout In addition to its Character.toUpperCase method. Java has a Character.toLowerCase method. With that in mind, write a program that reads a three-letter word and outputs the word as it’s capitalized when it’s a person’s name. For example, if the program reads the letters ann, the program outputs Ann. If the program inputs BoB, the program outputs Bob.

ARRANGEMENTS OF LETTERS

Write a program that reads three letters from the keyboard and outputs all possible arrangements of the three letters. For example, if the program reads the letters

box

the program outputs

box
bxo
obx
oxb
xbo
xob

The boolean Type

I’m in big trouble. I have 140 gumballs, and 15 kids are running around and screaming in my living room. They’re screaming because each kid wants 10 gumballs, and they’re running because that’s what kids do in a crowded living room. I need a program that tells me whether I can give 10 gumballs to each kid.

I need a variable of type boolean. A boolean variable stores one of two values — true or false (true, I can give ten gumballs to each kid; or false, I can’t give ten gumballs to each kid). Anyway, the kids are going berserk, so I’ve written a short program and put it in Listing 8-4. The output of the program is shown in Figure 8-9.

image

FIGURE 8-9: Oh, no!

LISTING 8-4 Using the boolean Type

class CanIKeepKidsQuiet {

public static void main(String args[]) {
int gumballs;
int kids;
int gumballsPerKid;
boolean eachKidGetsTen;

gumballs = 140;
kids = 15;
gumballsPerKid = gumballs / kids;

System.out.print("True or false? ");
System.out.println("Each kid gets 10 gumballs.");
eachKidGetsTen = gumballsPerKid >= 10;
System.out.println(eachKidGetsTen);
}
}

In Listing 8-4, the variable eachKidGetsTen is of type boolean. So the value stored in the eachKidGetsTen variable can be either true or false. (I can’t store a number or a character in the eachKidGetsTen variable.)

To find a value for the variable eachKidGetsTen, the program checks to see whether gumballsPerKid is greater than or equal to ten. (The symbols >= stand for “greater than or equal to.” What a pity! There’s no ≥ key on the standard computer keyboard.) Because gumballsPerKid is only nine, gumballsPerKid >= 10 is false. So eachKidGetsTen becomes false. Yikes! The kids will tear the house apart! (Before they do, take a look at Figure 8-10.)

image

FIGURE 8-10: Assigning a value to the eachKidGetsTen variable.

Expressions and conditions

In Listing 8-4, the code gumballsPerKid >= 10 is an expression. The expression’s value depends on the value stored in the variable gumballsPerKid. On a bad day, the value of gumballsPerKid >= 10 is false. So the variable eachKidGetsTen is assigned the value false.

An expression like gumballsPerKid >= 10, whose value is either true or false, is sometimes called a condition.

technicalstuff Values like true and false may look as though they contain characters, but they really don’t. Internally, the Java Virtual Machine doesn’t store boolean values with the letters t-r-u-e or f-a-l-s-e. Instead, the JVM stores codes, like 0 for false and 1 for true. When the computer displays a boolean value (as in System.out.println(eachKidGetsTen)), the Java Virtual Machine converts a code like 0 into the five-letter word false.

Comparing numbers; comparing characters

In Listing 8-4, I compare a variable’s value with the number 10. I use the >= operator in the expression

gumballsPerKid >= 10

Of course, the greater-than-or-equal-to comparison gets you only so far. Table 8-1 shows you the operators you can use to compare things with one another.

TABLE 8-1 Comparison Operators

Operator Symbol

Meaning

Example

==

is equal to

myGuess == winningNumber

!=

is not equal to

5 != numberOfCows

<

is less than

strikes < 3

>

is greater than

numberOfBoxtops > 1000

<=

is less than or equal to

lowNumber + highNumber <= 25

>=

is greater than or equal to

gumballsPerKid >= 10

With the operators in Table 8-1, you can compare both numbers and characters.

warning Notice the double equal sign in the first row of Table 8-1. Don’t try to use a single equal sign to compare two values. The expression myGuess = winningNumber (with a single equal sign) doesn’t compare myGuess with winningNumber. Instead, myGuess = winningNumber changes the value of myGuess. (It assigns the value of winningNumber to the variable myGuess.)

You can compare other things (besides numbers and characters) with the == and != operators. But when you do, you have to be careful. For more information, see Chapter 18.

Comparing numbers

Nothing is more humdrum than comparing numbers. “True or false? Five is greater than or equal to ten.” False. Five is neither greater than nor equal to ten. See what I mean? Bo-ring.

Comparing whole numbers is an open-and-shut case. But unfortunately, when you compare decimal numbers, there’s a wrinkle. Take a program for converting from Celsius to Fahrenheit. Wait! Don’t take just any such program; take the program in Listing 8-5.

LISTING 8-5 It’s Warm and Cozy in Here

import java.util.Scanner;

class CelsiusToFahrenheit {

public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
double celsius, fahrenheit;

System.out.print("Enter the Celsius temperature: ");
celsius = keyboard.nextDouble();

fahrenheit = 9.0 / 5.0 * celsius + 32.0;

System.out.print("Room temperature? ");
System.out.println(fahrenheit == 69.8);

keyboard.close();
}
}

If you run the code in Listing 8-5 and input the number 21, the computer finds the value of 9.0 / 5.0 * 21 + 32.0. Believe it or not, you want to check the computer’s answer. (Who knows? Maybe the computer gets it wrong!) You need to do some arithmetic, but please don’t reach for your calculator. A calculator is just a small computer, and machines of that kind stick up for one another. To check the computer’s work, you need to do the arithmetic by hand. What? You say you’re math-phobic? Well, don’t worry. I’ve done all the math in Figure 8-11.

image

FIGURE 8-11: The Fahrenheit temperature is exactly 69.8.

If you do the arithmetic by hand, the value you get for 9.0 / 5.0 * 21 + 32.0 is exactly 69.8. So run the code in Listing 8-5 and give celsius the value 21. You should get true when you display the value of fahrenheit == 69.8, right?

Well, no. Take a look at the run in Figure 8-12. When the computer evaluates fahrenheit == 69.8, the value turns out to be false, not true. What’s going on here?

image

FIGURE 8-12: A run of the code in Listing 8-5.

remember Grouping separators vary from one country to another. The run shown in Figure 8-12 works almost everywhere in the world. But if the Celsius temperature is twenty-one-and-a-half degrees, you type 21.5 (with a dot) in some countries and 21,5 (with a comma) in others. Your computer’s hardware doesn’t have a built-in “country-ometer,” but when you install the computer’s operating system, you tell it which country you live in. Java programs access this information and use it to customize the way the nextDouble method works.

A little detective work can go a long way. Review the facts:

  • Fact: The value of fahrenheit should be exactly 69.8.
  • Fact: If fahrenheit is 69.8, then fahrenheit == 69.8 is true.
  • Fact: In Figure 8-12, the computer displays the word false. So the expression fahrenheit == 69.8 isn’t true.

How do you reconcile these facts? There can be little doubt that fahrenheit == 69.8 is false, so what does that say about the value of fahrenheit? Nowhere in Listing 8-5 is the value of fahrenheit displayed. Could that be the problem?

At this point, I use a popular programmer’s trick. I add statements to display the value of fahrenheit:

fahrenheit = 9.0 / 5.0 * celsius + 32.0;
System.out.print("fahrenheit: "); //Added
System.out.println(fahrenheit); //Added

A run of the enhanced code is shown in Figure 8-13. As you can see, the computer misses its mark. Instead of the expected value 69.8, the computer’s value for 9.0 / 5.0 * 21 + 32.0 is 69.80000000000001. That’s just the way the cookie crumbles. The computer does all its arithmetic with zeros and ones, so the computer’s arithmetic doesn’t look like the base-10 arithmetic in Figure 8-11. The computer’s answer isn’t wrong. The answer is just slightly inaccurate.

image

FIGURE 8-13: The fahrenheit variable’s full value.

In an example in Chapter 7, Java’s remainder operator (%) gives you the answer 0.1299999999999999 instead of the 0.13 that you expect. The same strange kind of thing happens in this section’s example. But this section’s code doesn’t use an exotic remainder operator. This section’s code uses your old friends: division, multiplication, and addition.

Be careful when you compare two numbers for equality (with ==) or for inequality (with !=). Little inaccuracies can creep in almost anywhere when you work with Java’s double type or with Java’s float type. And several little inaccuracies can build on one another to become very large inaccuracies. When you compare two double values or two float values, the values are almost never dead-on equal to one another.

remember If your program isn’t doing what you think it should do, check your suspicions about the values of variables. Add print and println statements to your code.

technicalstuff When you compare double values, give yourself some leeway. Instead of comparing for exact equality, ask whether a particular value is reasonably close to the expected value. For example, use a condition like fahrenheit >= 69.8 - 0.01 && fahrenheit <= 69.8 + 0.01 to find out whether fahrenheit is within 0.01 of the value 69.8. To read more about conditions containing Java’s && operator, see Chapter 10.

Comparing characters

The comparison operators in Table 8-1 work overtime for characters. Roughly speaking, the operator < means “comes earlier in the alphabet.” But you have to be careful of the following:

  • Because B comes alphabetically before H, the condition ’B’ < ’H’ is true. That’s not surprising.
  • Because b comes alphabetically before h, the condition ’b’ < ’h’ is true. That’s no surprise, either.
  • Every uppercase letter comes before any of the lowercase letters, so the condition ’b’ < ’H’ is false. Now, that’s a surprise. (See Figure 8-14.)
image

FIGURE 8-14: The ordering of the letters.

In practice, you seldom have reason to compare one letter with another. But in Chapter 18, you can read about Java’s String type. With the String type, you can compare words, names, and other good stuff. At that point, you have to think carefully about alphabetical ordering, and the ideas in Figure 8-14 come in handy.

technicalstuff Under the hood, the letters A through Z are stored with numeric codes 65 through 90. The letters a through z are stored with codes 97 through 122. That’s why each uppercase letter is “less than” any of the lowercase letters.

The Remaining Primitive Types

In Chapter 7, I tell you that Java has eight primitive types, but Table 7-1 lists only six of eight types. Table 8-2 describes the remaining two types — the types char and boolean. Table 8-2 isn’t too exciting, but I can’t just leave you with the incomplete story in Table 7-1.

TABLE 8-2 Java’s Primitive Non-Numeric Types

Type Name

Range of Values

Character Type

char

Thousands of characters, glyphs, and symbols

Logical Type

boolean

Only true or false

technicalstuff If you dissect parts of the Java Virtual Machine, you find that Java considers char to be a numeric type. That’s because Java represents characters with something called Unicode — an international standard for representing alphabets of the world’s many languages. For example, the Unicode representation of an uppercase letter C is 67. The representation of a Hebrew letter Aleph is 1488. And (to take a more obscure example) the representation for the voiced retroflex approximant in phonetics is 635. But don’t worry about all of this. The only reason I’m writing about the char type’s being numeric is to save face among my techie friends.

technicalstuff After looking at Table 8-2, you may be wondering what a glyph is. (In fact, I’m proud to be writing about this esoteric concept, whether you have any use for the information or not.) A glyph is a particular representation of a character. For example, a and a are two different glyphs, but both of these glyphs represent the same lowercase letter of the Roman alphabet. (Because these two glyphs have the same meaning, the glyphs are called allographs. If you want to sound smart, find a way to inject the words glyph and allograph into a casual conversation!)

MORE CHARACTER METHODS

tryitout Type the boldface text, one line after another, into JShell, and see how JShell responds.

jshell> Character.isDigit(’a’)

jshell> Character.isDigit(’2’)

jshell> Character.isLetter(’a’)

jshell> Character.isLetter(’2’)

jshell> Character.isLetterOrDigit(’4’)

jshell> Character.isLetterOrDigit(’@’)

jshell> Character.isLowerCase(’b’)

jshell> Character.isLowerCase(’B’)

jshell> Character.isLowerCase(’7’)

jshell> Character.isJavaIdentifierPart(’x’)

jshell> Character.isJavaIdentifierPart(’7’)

jshell> Character.isJavaIdentifierPart(’-’)

jshell> Character.isJavaIdentifierPart(’ ’)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.240.252