Lesson 1.5 · Unit 1 · CED topic 1.5

Casting and the range of variables

Java keeps int and double apart on purpose, but real programs mix them all the time: an average of whole numbers, a price rounded to cents, a percentage of a count. This lesson covers the tool that converts between them, the cast, and the two ways numbers can quietly go wrong: values that fall out of an int's range and values a double cannot hold exactly.

Required content · LO 1.5.A, LO 1.5.B, LO 1.5.C

Learning objectives.

  • 1.5.A. Develop code to cast primitive values to different primitive types in arithmetic expressions and determine the value that is produced as a result.
  • 1.5.B. Describe conditions when an integer expression evaluates to a value out of range.
  • 1.5.C. Describe conditions that limit accuracy of expressions.

Essential knowledge.

  • 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).
  • 1.5.A.2. Casting a double value to an int value causes the digits to the right of the decimal point to be truncated.
  • 1.5.A.3. Some code causes int values to be automatically cast (widened) to double values.
  • 1.5.A.4. Values of type double can be rounded to the nearest integer by (int) (x + 0.5) for non-negative numbers or (int)(x - 0.5) for negative numbers.
  • 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.
  • 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.
  • 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.  
  • 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.
    Outside the course: Other special decimal data types that can be used to avoid rounding errors are outside the scope of the AP Computer Science A course and exam.

Casting with (int) and (double)

A casting operator converts a value to another type. The two you need are (int) and (double), written in parentheses directly before the value.

  • (int) on a double truncates: the digits to the right of the decimal point are dropped, with no rounding. (int) 3.99 is 3, and (int) -3.99 is -3, because truncation always moves toward zero.
  • (double) on an int produces the same number with a decimal part: (double) 4 is 4.0.
  • Some code casts automatically. An int used where a double is needed is widened to a double without a cast, which is why double x = 7; is legal and stores 7.0.
System.out.println((int) 3.99);
System.out.println((int) -3.99);
System.out.println((double) 4);
double widened = 7;
System.out.println(widened);
3
-3
4.0
7.0

### A cast binds tightly

A cast applies to the value immediately after it, before any arithmetic operator runs. That makes the position of the parentheses matter.

ExpressionValueWhy
(int) 3.7 * 26the cast happens first: 3 * 2
(int) (3.7 * 2)7multiply first (7.4), then truncate
(double) 7 / 23.5the cast turns 7 into 7.0 first, so real division
(double) (7 / 2)3.0integer division first (3), then widen

The second pair is the most useful pattern in the course. To compute an average of int values without losing the fraction, cast one operand before the division:

int sum = 17;
int count = 4;
System.out.println(sum / count);
System.out.println((double) sum / count);
System.out.println((double) (sum / count));
4
4.25
4.0

### Rounding to the nearest integer

A cast truncates, so to round you first nudge the value. For a non-negative x, (int) (x + 0.5) gives the nearest integer. For a negative x, (int) (x - 0.5) does. To round to a number of decimal places, scale up, round, and scale back down:

double price = 12.3456;
int nearestDollar = (int) (price + 0.5);
double nearestCent = (int) (price * 100 + 0.5) / 100.0;
System.out.println(nearestDollar);
System.out.println(nearestCent);
12
12.35

The range of an int

Integers in Java are stored in a fixed amount of memory (4 bytes), so an int can only hold values between two limits. Two constants name them.

ConstantValue
Integer.MAX_VALUE2147483647
Integer.MIN_VALUE-2147483648

If an expression would produce an int outside that range, integer overflow occurs. Java does not stop and does not warn. The result is an int that is in the allowed range but not the value you expected, because the value wraps around.

int big = Integer.MAX_VALUE;
System.out.println(big);
System.out.println(big + 1);
2147483647
-2147483648

When a double is not exact

A double also lives in a fixed amount of memory. Many decimal numbers, such as 0.1, have no exact binary representation, so the stored value is the nearest one that fits. Arithmetic on these values can produce a round-off error.

System.out.println(0.1 + 0.2);
System.out.println(0.1 + 0.2 == 0.3);
0.30000000000000004
false

The rule that follows: do not rely on exact equality of computed double values, and when exactness matters, use int values. A program that tracks money in whole cents with an int never accumulates this error.

Worked example · predicting the value of a cast expression

Give the value and the type of each expression.

int a = 9;
int b = 4;
double d = 2.5;
System.out.println(a / b);
System.out.println((double) a / b);
System.out.println((int) d * 3);
System.out.println((int) (d * 3));
System.out.println((int) (d + 0.5));
2
2.25
6
7
3
ExpressionReasoningValue
a / bboth int, so integer division2 (an int)
(double) a / bcast first, then 9.0 / 42.25 (a double)
(int) d * 3(int) 2.5 is 2, times 36 (an int)
(int) (d * 3)7.5 truncated7 (an int)
(int) (d + 0.5)3.0 truncated3 (an int)
Worked example · an average that comes out wrong

A program computes the average of three test scores and displays 88.0, though the real average is 88.33.

int s1 = 90;
int s2 = 85;
int s3 = 90;
double wrong = (s1 + s2 + s3) / 3;
double right = (s1 + s2 + s3) / 3.0;
System.out.println(wrong);
System.out.println(right);
88.0
88.33333333333333

The sum is 265, an int, and 265 / 3 is integer division: it throws away .33 before the result is ever stored in the double. The fix is to make one operand a double. Writing 3.0 does it, and so does (double) (s1 + s2 + s3) / 3.

Worked example · counting dollars in cents

A program totals items that cost 1.10 and 2.20 dollars, then repeats the calculation in whole cents.

double dollars = 1.10 + 2.20;
int cents = 110 + 220;
System.out.println(dollars);
System.out.println(cents / 100 + " dollars and " + cents % 100 + " cents");
3.3000000000000003
3 dollars and 30 cents

The double total is slightly off, a round-off error, because neither 1.10 nor 2.20 is stored exactly. The int version is exact for every input, because whole numbers within the int range are stored exactly. Use / and % to split cents into dollars and cents.

Exam focus

Expect a question that asks for the value of an expression with casts in different positions, and one that asks what happens when a value exceeds Integer.MAX_VALUE (an in-range but wrong value, never an error message). Also expect the average pattern: the exam wants you to notice that the cast must come before the division. Know the rounding formula (int) (x + 0.5) for non-negative values. Other special decimal types that avoid round-off error are outside the course.

Practice
  1. What is printed?
    double x = 8.9;
    int y = (int) x;
    System.out.println(y);
    System.out.println((int) -x);
    Show answer

    8 and -8. The cast truncates toward zero, so 8.9 becomes 8 and -8.9 becomes -8. It does not round.

  2. What is printed?
    int total = 7;
    int n = 2;
    System.out.println(total / n);
    System.out.println((double) total / n);
    System.out.println((double) (total / n));
    Show answer

    3, 3.5, 3.0. The first is integer division. In the second the cast makes total a double before dividing. In the third the division is already finished (giving 3) before the cast widens it.

  3. Complete the statement so that pct holds the percent of questions answered correctly as a double (for 17 of 20 it should hold 85.0).
    int correct = 17;
    int total = 20;
    double pct = 100.0 * correct / total;
    System.out.println(pct);
    Show answer

    100.0 * correct / total multiplies first (left to right) with a double, giving 1700.0, then divides by 20. Writing 100 * correct / total would have used integer arithmetic throughout, which gives 85 here but would give 62 for 5 correct out of 8 instead of 62.5.

  4. A student claims the code below throws an exception. Explain what really happens.
    int n = Integer.MAX_VALUE;
    n = n + 1;
    System.out.println(n);
    Show answer

    No exception occurs. The sum is outside the int range, so integer overflow produces a different int in the allowed range. Here it wraps to Integer.MIN_VALUE, which is -2147483648.

  5. Write an expression that rounds the non-negative double variable grade to the nearest integer.
    double grade = 86.5;
    int rounded = (int) (grade + 0.5);
    System.out.println(rounded);
    Show answer

    (int) (grade + 0.5). Adding 0.5 pushes any fractional part of 0.5 or more up to the next whole number, and the cast then truncates, so 86.5 becomes 87.

  6. Why is 0.1 + 0.2 == 0.3 false, and how can a program avoid this kind of surprise when counting money?
    Show answer

    A double stores the nearest representable value, and 0.1 and 0.2 are not stored exactly, so their sum differs slightly from the stored 0.3 (a round-off error). Storing money in whole cents in an int avoids it, because integers in range are exact.

← 1.4 Assignment statements and input1.6 Compound assignment operators →

Keep going in the full AP Computer Science A course

All of U1 (Using Objects and Methods) is free to everyone, with no account. The course has 58 lessons, each with worked examples and practice problems that come with full solutions. A free account can also start a free month of the whole course, with no card.

Open this lesson in the courseSee the whole course