Unravel โบ Java concepts โบ Numbers and math
Primitive types and floating point
Java has eight primitive types (byte short int long float double char boolean).
At a glance
Measuring with a ruler marked in halves, quarters and eighths: some lengths (like a tenth) fall between the marks, so you always get the nearest mark.
- 1Whole numbers: int (about ยฑ2.1 billion), long (about ยฑ9.2 quintillion, write 10L)Fractions: double (default for 1.5), float (write 1.5f). Division of two ints discards the fraction: 7 / 2 is 3.
- 2Compare floating-point numbers with a tolerance (Math.abs(a - b) < 1e-9), never with ==For money use BigDecimal or whole cents in a long.
- 3Special values: NaN (not a number, never equal to anything, including itself, test with Double.isNaN), Infinity (from dividing by zero for doubles; integer division by zero throws ArithmeticException)
- 4Widening is automatic (int to long to double); narrowing needs a cast and can lose data: (int) 3.99 is 3, and (byte) 200 is -56
- Floating-point sums depend on the order of the additions, so summing the same list in parallel can give slightly different totals
- float has about 7 decimal digits of precision and double about 15 to 16
- double is IEEE 754 binary64: 1 sign bit, 11 exponent bits, 52 fraction bits
public class Average { static double average(int[] values) { long sum = 0; for (int v : values) sum += v; return values.length == 0 ? Double.NaN : (double) sum / values.length; } static boolean close(double a, double b) { return Math.abs(a - b) < 1e-9; }}Read the full explanation (about 2 min)
Java has eight primitive types (byte short int long float double char boolean). double and float are binary fractions: they cannot store 0.1 exactly, so 0.1 + 0.2 is 0.30000000000000004.
A mental model
Measuring with a ruler marked in halves, quarters and eighths: some lengths (like a tenth) fall between the marks, so you always get the nearest mark.
How it works
Whole numbers: int (about ยฑ2.1 billion), long (about ยฑ9.2 quintillion, write 10L). Fractions: double (default for 1.5), float (write 1.5f). Division of two ints discards the fraction: 7 / 2 is 3.
Compare floating-point numbers with a tolerance (Math.abs(a - b) < 1e-9), never with ==. For money use BigDecimal or whole cents in a long.
Special values: NaN (not a number, never equal to anything, including itself, test with Double.isNaN), Infinity (from dividing by zero for doubles; integer division by zero throws ArithmeticException).
Widening is automatic (int to long to double); narrowing needs a cast and can lose data: (int) 3.99 is 3, and (byte) 200 is -56.
Going deeper
Floating-point sums depend on the order of the additions, so summing the same list in parallel can give slightly different totals.
float has about 7 decimal digits of precision and double about 15 to 16. A long ID stored in a double above 2^53 silently loses digits (a classic JavaScript and JSON issue too).
char is an unsigned 16-bit number; short and byte arithmetic is done as int, so byte b = b1 + b2; needs a cast.
Under the hood
double is IEEE 754 binary64: 1 sign bit, 11 exponent bits, 52 fraction bits. Primitives live on the stack (locals) or inside objects and arrays, and have no object overhead.
Common mistakes
- Using
==on doubles. - Using
doublefor money. - Integer division where a fraction was expected (
sum / count). - Forgetting the
Lsuffix on a big long literal.
How Unravel recognises it
When you paste code, Unravel looks for these signs of primitive types and floating point. Spotting them yourself is a good habit when you read unfamiliar code:
- Method calls:
Double.compare()isNaN()isInfinite()Double.parseDouble() - Constants:
Double.NaNDouble.MAX_VALUEDouble.POSITIVE_INFINITY - Language constructs:
float-literal
Part of a learning path
- Text, numbers and arrays ยท previous: Characters, Unicode and encodings ยท next: Integer overflow and exact arithmetic
Related concepts
Builds on this
Frequently asked questions
What is Primitive types and floating point?
Java has eight primitive types (byte short int long float double char boolean). double and float are binary fractions: they cannot store 0.1 exactly, so 0.1 + 0.2 is 0.30000000000000004.
What are the most common mistakes with Primitive types and floating point?
Using == on doubles. Using double for money. Integer division where a fraction was expected (sum / count). Forgetting the L suffix on a big long literal.
How can I see Primitive types and floating point in real code?
Paste your own Java into Unravel and it will point out where primitive types and floating point appears, explain how it works at the detail level you choose, and draw the flow of the code around it.