Lesson 1.5: Casting and Range of Variables | AP CSA
Lesson 1.5: Casting and Range of Variables
What you'll learn in this lesson
-
1.5.A. Use
(int)and(double)casts to convert between types, predict the result of truncation, and recognize when widening happens automatically. -
1.5.A. Apply the rounding formula
(int)(x + 0.5)for non-negative doubles. -
1.5.B. Explain integer overflow using
Integer.MAX_VALUEandInteger.MIN_VALUE, and describe what happens when an int expression exceeds the allowed range. - 1.5.C. Describe how double round-off error occurs when a value is more precise than memory allows.
This lesson is part of the AP CSA Course and Exam Description (effective May 2027).
AP exam weight: Casting questions appear on nearly every exam. The most common trap is cast-scope: (int) 2.9 + 1 vs (int)(2.9 + 1) produce different results because the cast only applies to the immediately following operand.
Key Vocabulary
| Term | Definition |
|---|---|
| cast operator | A type name in parentheses, e.g. (int) or (double), that forces a type conversion. |
| truncation | Dropping all digits after the decimal point when casting double to int; 9.9 becomes 9. |
| widening | Automatic promotion from int to double; no cast required. |
| Integer.MAX_VALUE | The largest value an int can hold: 2,147,483,647 (2^31 - 1). |
| Integer.MIN_VALUE | The smallest value an int can hold: -2,147,483,648 (-2^31). |
| integer overflow | When an int expression produces a value outside the allowed range; the value wraps around silently. |
| round-off error | Imprecision in double values because some decimals cannot be represented exactly in binary floating-point. |
| rounding formula | (int)(x + 0.5) rounds a non-negative double to the nearest integer by truncating after adding 0.5. |
Casting: converting between primitive types
A cast forces a value from one numeric type to another. Java provides two casting operators for primitives: (int) and (double).
The Two Cast Operators
(int) expression — converts a double to an int by dropping all digits after the decimal point (truncation, not rounding).
(double) expression — converts an int to a double, adding a decimal point. No information is lost.
Examples
double d = 9.99; int n = (int) d; // n = 9 (truncated, not rounded) int x = 5; double r = (double) x; // r = 5.0 double avg = (double) 7 / 2; // 7 cast to 7.0, then 7.0/2 = 3.5 double bad = (double)(7 / 2); // 7/2 = 3 first (int div), then cast to 3.0
AP Trap: cast scope
A cast operator applies only to the immediately following operand, not the whole expression. (int) 2.9 + 1.6 casts only 2.9 to 2, then adds 1.6, giving 3.6. To cast the entire sum, use parentheses: (int)(2.9 + 1.6) gives 4.
Widening: automatic int-to-double promotion
When an int value is used where a double is expected, Java automatically widens it. This happens without a cast whenever: you assign an int to a double variable, or you use an int and a double together in an arithmetic expression.
Widening is Automatic; Narrowing Requires a Cast
double d = 5; — valid, 5 widens to 5.0.
int n = 5.0; — compile error, narrowing requires explicit (int) cast.
Rounding a double to the nearest integer
Because (int) truncates toward zero, rounding requires adding 0.5 before casting.
Rounding Formula (non-negative values)
int rounded = (int)(x + 0.5);
Examples: x = 3.2 → 3.2 + 0.5 = 3.7 → truncates to 3. x = 3.7 → 4.2 → truncates to 4.
Integer range and overflow
Java uses exactly 4 bytes (32 bits) to store an int. This limits the allowed range.
The Constants
Integer.MAX_VALUE = 2,147,483,647 (231 − 1)
Integer.MIN_VALUE = −2,147,483,648 (−231)
If an arithmetic expression would produce a value outside this range, integer overflow occurs. Java does not throw an exception. Instead, the value wraps around to the other end of the range.
Overflow Wraps, Not Crashes
int big = Integer.MAX_VALUE; big = big + 1; // overflows to Integer.MIN_VALUE (-2147483648)
The program keeps running with the wrong value. No exception is thrown. This is one reason to use long when dealing with very large numbers in real programs—but long is outside the scope of the AP exam.
Double round-off error
Computers store double values in a fixed amount of memory (8 bytes). Some decimal values cannot be represented exactly in binary floating point. When a value is more precise than the memory can hold, a round-off error occurs: the stored value is the nearest representable number.
Classic Example
System.out.println(0.1 + 0.2); // prints 0.30000000000000004
To minimize round-off errors, prefer int arithmetic whenever exact results are required (for example, work in cents rather than dollars).
AP Scope Note
Other decimal types that avoid round-off errors (such as BigDecimal) are outside the scope of the AP exam. You need to know that round-off error exists and when it occurs, but you will not be asked to use alternative types.
Practice Questions
result after the following statement executes?double result = (double)(5 / 2) + (double) 1 / 4;
5 / 2 is int division = 2; then (double) 2 = 2.0. Right side: (double) 1 = 1.0; then 1.0 / 4 = 0.25 (double / int = double). Sum: 2.0 + 0.25 = 2.25. A would result if 5/2 gave 2.5. B would result if both sides rounded up. C uses 5/2 = 2.5 incorrectly.
double d = 7.9; int trunc = (int) d; int rounded = (int)(d + 0.5); System.out.println(trunc + " " + rounded);
(int) 7.9 truncates to 7. 7.9 + 0.5 = 8.4; (int) 8.4 truncates to 8. Prints 7 8. A is wrong because truncation drops the decimal, it does not round. C applies truncation to both. D adds an extra 1 incorrectly.
3.5?I.
(double) 7 / 2II.
(double)(7 / 2)III.
7 / (double) 2
7 first, giving 7.0. Then 7.0 / 2 = 3.5 (double / int). Expression II: 7 / 2 = 3 first (int division), then cast gives 3.0—not 3.5. Expression III: cast applies to 2, giving 2.0. Then 7 / 2.0 = 3.5 (int / double). I and III both produce 3.5; II produces 3.0.
int n = Integer.MAX_VALUE; n = n + 1; System.out.println(n);
Which of the following best describes what happens?
Integer.MAX_VALUE is not allowed.ArithmeticException is thrown at run time because the value exceeds the int range.Integer.MIN_VALUE because integer overflow wraps the value to the minimum.2147483648 because Java automatically promotes n to long.Integer.MAX_VALUE (2,147,483,647) wraps around to Integer.MIN_VALUE (−2,147,483,648). No exception is thrown and no error is reported. A is wrong: the compiler allows this. B is wrong: overflow does not throw an exception for integer types. D is wrong: Java does not auto-promote int to long on overflow.
I.
double d = 4;II.
int n = 4.0;III.
int m = (int) 4.0;
int 4 to double is widening—valid. Statement II: assigning double 4.0 to int is narrowing without a cast—compile error. Statement III: (int) 4.0 explicitly casts 4.0 to 4, then assigns to int—valid. Only II fails.
0.3 but gets a different result.double x = 0.1 + 0.2; System.out.println(x);
Which of the following best explains the unexpected output?
+ operator does not work correctly with double values; Math.add should be used instead.0.1 and 0.2 are stored as int values internally, so their sum truncates.x should be declared as float rather than double to get exact decimal arithmetic.0.1 and 0.2 cannot be represented exactly in binary floating point, so their stored values differ slightly from the true decimal values, producing a round-off error in the sum.0.1 is stored as the nearest representable binary value, which is slightly more than 0.1. The same is true for 0.2. Their sum is slightly more than 0.3, producing output like 0.30000000000000004. A is wrong: + works correctly with doubles. B is wrong: they are stored as doubles, not ints. C is wrong: float also has round-off error and is less precise.
I. Integer overflow throws an
ArithmeticException at run time.II. If
Integer.MAX_VALUE is incremented by 1, the result equals Integer.MIN_VALUE.III. Java automatically promotes an
int variable to long when overflow would occur.Which of the statements above are TRUE?
Integer.MAX_VALUE + 1 wraps to Integer.MIN_VALUE due to binary arithmetic. Statement III is FALSE: Java does not automatically promote to long on overflow. The variable stays int with the wrapped value.
result after the following statement executes?int result = (int)(3.6 + 2.9);
3.6 + 2.9 = 6.5 (double arithmetic inside the parentheses). Then (int) 6.5 truncates to 6. B would result from casting each value individually and adding: (int)3.6 + (int)2.9 = 3 + 2 = 5. C would result from rounding up. D is wrong because the cast to int produces an integer.
Output Predictor — Casting
Predict the exact printed value after each cast or conversion.
Bug Hunt — Casting
Each snippet has exactly one buggy line. Click it, then submit.
The Track Team Timer
A student writes a program that reads a runner's time in seconds (as a double) and computes the whole seconds and the tenths of a second separately for display. A classmate tests it and finds the output is wrong.
double rawTime = 12.7; int wholeSeconds = (int) rawTime; int tenths = (int)((rawTime - wholeSeconds) * 10); System.out.println(wholeSeconds + "." + tenths);
Part A: Predict the output
rawTime = 12.7?wholeSeconds? What is rawTime - wholeSeconds? Then what is tenths?wholeSeconds = (int) 12.7 = 12. rawTime - wholeSeconds = 12.7 - 12 = 0.7 in theory, but due to double round-off error the stored value of 0.7 is slightly less than 0.7 (approximately 0.699999...). Multiplying by 10 gives approximately 6.9999..., and (int) truncates that to 6. So tenths = 6 and the program prints 12.6. This is the round-off error trap.
Part B: Identify the fix
tenths correctly stores 7?int tenths = (int)((rawTime - wholeSeconds) * 10 - 0.5);
int tenths = (int)((rawTime - wholeSeconds) * 10 + 0.5);
int tenths = (int) rawTime % 10;
int tenths = (int)(rawTime * 10) - wholeSeconds;
0.6999... * 10 = 6.999...; adding 0.5 gives 7.499..., which truncates to 7. A subtracts 0.5, making the problem worse. C extracts the tens digit of the truncated integer (which is wrong). D: (int)(rawTime * 10) = (int)(127.0) = 127, then 127 - 12 = 115—completely wrong.
Part C: Structured response
A teammate suggests storing money as a double (e.g., double price = 0.10) and adding values like 0.10 + 0.20 to compute totals. In three to five sentences, explain why this approach risks incorrect results, what Java concept causes the problem, and what strategy avoids it.
Scoring Rubric (4 points)
- +1: Names the problem: double round-off error (or floating-point representation error).
- +1: Explains cause: decimal values like 0.1 and 0.2 cannot be represented exactly in binary floating point; the stored values differ slightly from the true decimal values.
-
+1: Gives a concrete example:
0.1 + 0.2prints0.30000000000000004, not0.3. -
+1: States the avoidance strategy: store monetary values as
intcents (e.g., 10 cents, 20 cents) and perform integer arithmetic, converting to dollars only for display.
BigDecimal for exact decimal arithmetic
java.math.BigDecimal stores decimal values exactly using arbitrary-precision arithmetic. new BigDecimal("0.1").add(new BigDecimal("0.2")) returns exactly 0.3. It is slower than double and more verbose, but it is the right tool whenever exact decimal results matter—financial calculations, tax computations, currency conversions. It is outside the AP exam scope but worth knowing exists.
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]