# 1.5 Casting and Ranges of Values

Each coding exercise has its own folder. Open its `.java` file and press **Run** to try it. **Run Tests** checks every graded exercise in this lesson at once.

## Casting

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.

![Bronze casting changes the shape of the metal.](images/bronze-casting.jpg)

*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. The casting operators `(int)` and `(double)` can be used to convert from a double value to an int value (or vice versa). For example, `(double) 1 / 3` will evaluate to a `double` value `0.33333333` instead of an `int` truncated value `0`. And `(int) 3.6` will evaluate to an `int` value `3` instead of a `double`. Casting an `int` value to a `double` adds on digits to the right of the decimal point. And casting `double` value to an `int` value causes the digits to the right of the decimal point to be truncated.

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

### Exercise 1

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?

> Open the `01-cast-division` folder and edit `Casting.java`. Press **Run** to try it; **Run Tests** checks it (1 test).

When Java divides two `int`s, 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`. This code causes int values like 10 to be automatically cast (widened) to double values like 10.0.

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:

```java
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`.

> `int`s in Java are always 32-bit signed values which mean they can represent values from -2³¹ to 2³¹ - 1, inclusive, while the range of consecutive integer values that can be represented by a double is from -2⁵³ to 2⁵³, 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`.

## Rounding

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)`:

```java
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`.

### Exercise 2

Run the code 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.

> Open the `02-nearestInt` folder and edit `NearestInt.java`. Press **Run** to try it; **Run Tests** checks it (1 test).

## Range of Values

What happens to repeating decimal numbers like 3.333333…? Such numbers can’t be represented exactly in any finite number of digits so computers have to store an approximation. Java’s `double`s can store about 14-15 digits worth of precision which is plenty for most purposes but 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. The constant `Integer.MAX_VALUE` holds the value of the largest possible int value in Java which is 2147483647, and `Integer.MIN_VALUE` holds the smallest int value -2147483648. Values in an `int` variable must be within the range of `Integer.MIN_VALUE` and `Integer.MAX_VALUE` inclusively. 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 the code below to see the range of values that can be stored in an `int` variable. If the compiler did not catch these out of range errors, they would lead to an overflow error during runtime.

### Exercise 3

Try the code to see that the values given to two variables are out of range for ints. An int cannot hold that many digits! Fix the problem by deleting the last 0 in the numbers to store less digits. The last print statement shows a runtime overflow error where `Integer.MAX_VALUE + 1` wraps around to evaluate to `Integer.MIN_VALUE` which is an incorrect result for the expression.

> Open the `03-overfl` folder and edit `TestOverflow.java`. Press **Run** to try it; **Run Tests** checks it (1 test).

Computers allot a specified amount of memory to store data based on the data type. For `double` values, computers allot twice as much memory than for `int`s—8 bytes rather than 4. However it’s still possible that an expression would evaluate to a mathematical value that requires more precision than can be stored in even 8 bytes. In that case a round-off error occurs and the result is rounded to the nearest `double` representable in 8 bytes. For example, repeating decimals like 0.333333333333333333 will be cut off after about 15 digits. To avoid round-off errors, you can choose to round the result to a specified number of digits after the decimal point or to an `int` value.

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](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.

### Exercise 4

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

> Open the `04-double-precision` folder and edit `TestFormat.java`. Press **Run** to try it; **Run Tests** checks it (1 test).

> Check your understanding: True or false: Java rounds up automatically when you do integer division. — answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-1-5-casting.html#q_round

> Check your understanding: True or false: casting always results in a double type. — answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-1-5-casting.html#q_cast

## Coding 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 starter code, 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 in the starter file.

### Exercise 5

Type in three made up int grades and then sum and average them. Use type casting to report the result as a double.

> Open the `05-challenge1-5-average` folder and edit `Challenge1_6.java`. Press **Run** to try it; **Run Tests** checks it (4 tests).

## 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](https://en.wikipedia.org/wiki/List_of_Unicode_characters) 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 2¹⁶ 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 2¹⁶ 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 2024, 154,998 codepoints have actually been assigned characters.)

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](https://unicodelookup.com/#cjk/1), and an [emoji](http://unicode.org/emoji/charts/full-emoji-list.html). Then look up other characters at this [Unicode Lookup](https://unicodelookup.com/) 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?

### Exercise 6

Can you print out a letter from 3 different languages using this [Unicode Lookup](https://unicodelookup.com/) site?

> Open the `06-challenge1-6-unicode` folder and edit `ChallengeUnicode.java`. This bonus is not graded, so check it yourself.

## Summary

- **Type casting** is used to convert a value from one type to another.
- (AP 1.5.A.1) The casting operators `(int)` and `(double)` can be used to convert from a double value to an int value (or vice versa).
- (AP 1.5.A.2) 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).
- (AP 1.5.A.3) Some code causes int values to be automatically cast (widened) to double values. In expressions involving `double`s, the `double` values are contagious, causing `int`s in the expression to be automatically converted (“widened”) to the equivalent `double` value so the result of the expression can be computed as a `double`.
- (AP 1.5.A.4) Values of type `double` can be rounded to the nearest integer by (int)(x + 0.5) or (int)(x - 0.5) for negative numbers.
- (AP 1.5.B.1) The constant `Integer.MAX_VALUE` holds the value of the largest possible int value. The constant `Integer.MIN_VALUE` holds the value of the smallest possible int value.
- (AP 1.5.B.2) 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.
- (AP 1.5.B.3) If an expression would evaluate to an int value outside of the allowed range, an **integer overflow** occurs. The result is an int value in the allowed range but not necessarily the value expected.
- (AP 1.5.C.1) Computers allot a specified amount of memory to store data based on the data type. If an expression would evaluate to a double that is more precise than can be stored in the allotted amount of memory, a **round-off error** occurs. The result will be rounded to the representable value. To avoid rounding errors that naturally occur, use int values or round doubles to the precision needed.

## AP Practice

> Check your understanding: Which of the following returns the correct average for a total that is the sum of 3 int values? — answer it on CS Awesome: https://runestone.academy/ns/books/published/csawesome2/topic-1-5-casting.html#AP_casting
