Time estimate: 45 min.

1.6. Casting and Ranges of Values

In Java, type casting is used to convert values from one type to another. By casting we don’t mean something to do with fishing, but it is a similar idea to casting a bronze, without needing to heat anything to 913 degrees Celsius. But like molten bronze is reshaped by melting it and pouring it into a mold, our data is reshaped via a cast operator. In Java when you cast you are changing the “shape” (or type) of the value.

../_images/bronze-casting.jpg

Figure 1: Bronze casting changes the shape of the metal.

The cast operator, which looks like (int) and (double) placed before any expression (a literal, a number, a variable, or more complex expression in parentheses) produces a value of the given type by converting the value of the original expression to the new type.

For example, (double) 1 / 3 will evaluate to a double value instead of an int. Run this code to find how Java handles division and what casting can do to the results. Notice what happens when you divide an int by an int or an int by a double or an int cast to a double divided by an int.

What happens when you divide an int by an int or with a double operand or with the type cast (double) or (int) on one of the operands? Add another line that divides 5 by 2 using a (double) cast. What is the result?

When Java divides two ints, it produces an int result by truncating the actual mathematical result, removing anything after the decimal point. Thus 9 / 10 evaluates to 0, not 0.9. It also does not evaluate to 1; truncating is not the same as rounding!

But in any expression involving a double, the double is “contagious” and will cause the value of that expression to also be a double. Thus the expression 9.0 / 10 is evaluated as if it had been written 9.0 / 10.0 and produces the double value 0.9.

Casting an int to double, as shown in the code above, produces a double value which will then causes any expression it is part of to produce a double. This is especially useful when you have int variables that you want to do non-integer division with:

int total; // a variable containing the sum of a bunch of ints
int count; // the number of ints that went into total

// Compute the average of the bunch of ints summed into total.
double average = (double) total / count;

A conversion from int to double is called a widening conversion because a double can represent any int value but not vice versa; thus a double is considered a wider data type than an int.

Note

ints in Java are always 32-bit signed values which mean they can represent values from \(-2^{31}\) to \(2^{31} - 1\), inclusive, while the range of consecutive integer values that can be represented by a double is from \(-2^{53}\) to \(2^{53}\), inclusive. (A double can also represent much larger values but with limited precision.) You can refer to the minimum and maximum int values with the constants Integer.MIN_VALUE and Integer.MAX_VALUE.

Values of type double in the range that can be represented by an int can be rounded to the nearest int by adding or subtracting 0.5 and then casting the result with (int):

double number;    // positive value from somewhere
double negNumber; // negative value from somewhere

int nearestInt = (int)(number + 0.5);
int nearestNegInt = (int)(negNumber – 0.5);

For example, if you divide 7.0 / 4.0 you get 1.75. If you cast that to an int, it will be truncated to 1. However if we want to round a double rather than truncating it, adding 0.5 will produce a number that is above the next integer value if the decimal part is greater than 0.5, as it is here. Then casting that value to an int will truncate down. So in this case 1.75 + 0.5 gives us 2.25 which is then truncated to 2. On the other hand adding 0.5 to the result of evaluating 5.0 / 4.2, namely 1.25, only gets us to 1.75 which truncates back to 1 which is the nearest integer to 1.25.

Run the code below to see how the formula of adding or subtracting .5 and then casting with (int) rounds a positive or negative double number to the closest int. Add a line of code that rounds number + 2.3 to the nearest int.

What happens to repeating decimal numbers like 3.333333…? Java limits the number of digits you can save for any double number to about 14-15 digits. You should be aware that the accuracy of any calculation on a computer is limited by the fact that computers can only hold a limited number of digits.

For example, int values are stored in 4 bytes of memory. There is an Integer.MAX_VALUE defined as 2147483647 and an Integer.MIN_VALUE defined as -2147483648. If you try to store any number larger or smaller than these numbers in an int variable, it will result in an integer overflow where an incorrect value could be stored. Try it below.

Try the code below to see two integer overflows for a positive and negative number. An int cannot hold that many digits! Fix the integer overflow by deleting the last 0 in the numbers to store less digits.

Although it’s not on the AP exam, you can format long decimal numbers to just show 2 digits after the decimal point with the following code using printf a formatted print method or format instead of println. It takes a format string like %.02f which tells printf to print a floating point number indicated by the % with 2 digits after the decimal point. See https://docs.oracle.com/javase/tutorial/java/data/numberformat.html for more information. You can also use escape characters like \\n in the format string to do a newline. Try it below.

Run the code below to see how a decimal number can be formatted to show 2 digits after the decimal point. Try it with 2.0/3.

exercise Check your understanding

1.6.1. groupwork Programming Challenge : Average 3 Numbers

This would be a good project to work together in pairs, and switch drivers (who has control of the keyboard in pair programming) after every line of code. In the code below, type in three made up int grades and then sum and average them. Use casting to report the result as a double. For example, if the grades are 90, 100, and 94, the sum of the three numbers is 90 + 100 + 94 = 284, and the average is the sum 284 divided by 3 which casted to a double is 94.666667. You should use your variables instead of the numbers in your formulas. Follow the pseudocode below.

Type in three made up int grades and then sum and average them. Use type casting to report the result as a double. If you do this challenge on replit.com (see template and links below), please paste your repl link here to turn it in.

Your teacher may suggest that you use a different Java IDE for this challenge so that you can use input to get these values using the Scanner class, for example with this JuiceMind template or replit template that you can use if you want to try the challenge with input.

1.6.2. Bonus Challenge : Unicode

If you get done early with the previous challenge, here’s something else fun you can do in Java, although it’s not covered in the AP exam.

Java was one of the first programming languages to use Unicode for its characters rather than ASCII. While ASCII could represent 128 characters which was plenty for English, Unicode is an international standard that tries to assign a number (which they like to call a “codepoint”) to every character in every language. Unicode codepoints are traditionally represented in hex code (a base 16 code that uses the digits 0-9 and the letters A-F for 10-15), so you might see things like U+1F600. But they’re just numbers. That last one is the same as 128512.

When Java was released in an 1996, Unicode had been around for five years and the Unicode people had declared they would only ever need 216 or 65,536 code points to represent all the characters used in the world. So Java included a char data type that can hold exactly 216 values. Then, seven months later, the Unicode folks, said, “Ooops, that’s not enough”, and extended their system to its current size of 1,112,064 possible codepoints. (As of September 2022, 149,186 have actually been used.)

That made char kind of obsolete. But while not every Unicode codepoint can be represented in a Java char, you can use an int to represent a codepoint and the method Character.toString to translate an int into a String containing the character for that codepoint. (You might see older Java code that casts numbers to char; for many codepoints that will work but not on more recently added codepoints including, critically those for Emoji. 😞 So better to use Character.toString and ignore char.)

Try the following program which prints out an English “A”, a Chinese character, and an emoji. Then look up other characters at this Unicode Lookup site and change the code to print them out. (Use the Dec column in site to get the decimal number.) Can you print out letters from 3 different languages?

Can you print out a letter from 3 different languages using this Unicode Lookup site?

1.6.3. Summary

  • Type casting is used to convert value from one type to another.

  • The casting operators (int) and (double) can be used to create a temporary value converted to a different data type.

  • Casting a double value to an int causes the digits to the right of the decimal point to be truncated (cut off and thrown away).

  • In expressions involving doubles, the double values are contagious, causing ints in the expression to be automatically converted to the equivalent double value so the result of the expression can be computed as a double.

  • Values of type double can be rounded to the nearest integer by (int)(x + 0.5) or (int)(x – 0.5) for negative numbers.

  • Integer values in Java are represented by values of type int, which are stored using a finite amount (4 bytes) of memory. Therefore, an int value must be in the range from Integer.MIN_VALUE to Integer.MAX_VALUE, inclusive.

  • If an expression would evaluate to an int value outside of the allowed range, an integer overflow occurs. This could result in an incorrect value within the allowed range.

You have attempted of activities on this page