1. Floating-point numbers
Suppose you decide to write a simple calculator. Or any other program where calculations are needed (from trivial money counting to complex physics). Not everything in real life is an integer—and there’s nothing you can do about it!
So let’s arm ourselves with a new data type!
In programming, fractional numbers are also called real numbers, or floating-point numbers (floating-point). In Java, as in most languages, they are used to store not only integers but also “fractional” values: things like 3.14, -28.57, 2.718281828...
Floating-point numbers come in two primary types:
| Type | Stores | Value range (approximate) | Precision | Typical size |
|---|---|---|---|---|
|
Numbers | ±1.5 × 10-45 ... ±3.4 × 1038 | ~7 significant digits | 4 bytes |
|
Numbers | ±5.0 × 10-324 ... ±1.7 × 10308 | ~15–16 significant digits | 8 bytes |
The float type
The float type gets its name from floating-point number—a number with a floating decimal point. Real numbers are mathematical objects with certain properties. Computers, however, have many limitations. So it’s not quite accurate to call fractional numbers in Java “real numbers”. The term used is “floating-point numbers”.
The float type typically stores 7 significant digits (for example, 0.1234567), a power of ten, and takes 4 bytes in memory. That’s too little for precise computations, so everyone quickly moved to double-precision numbers.
The double type
The double type gets its name from double precision. It occupies 8 bytes of memory (2 times more than float) and can hold up to 15 significant digits: 0.123456789012345. This is generally sufficient for most computations with fractional numbers, which is why double is the primary type for storing floating-point numbers in Java.
In this lecture the focus will be on double: it is recommended by default for all “ordinary” floating-point values. But we will also consider the float type later.
2. Declaration and initialization of double variables
Everything is like with int—only now we use double.
// Declare a variable and assign it the value of Pi
double pi = 3.1415926;
// You can declare without initializing
double averageSalary;
averageSalary = 91234.56;
// You can do calculations!
double pizzaPieces = 8;
double friends = 3;
double piecesPerFriend = pizzaPieces / friends; // 2.666... (not 2)
Syntax notes:
- Use a dot as the decimal separator (3.14). If you use a comma—you’ll get a compilation error!
- Strictly speaking, writing double d = 3; won’t cause an error—the types are converted automatically (the integer becomes a “floating-point” value without loss).
3. Input and output of floating-point numbers with Scanner
First, let’s print a floating-point number:
double amount = 42.75;
System.out.println(amount); // Will print: 42.75
All good! What if we add some text:
System.out.println("Your account balance: " + amount + " euros."); // Your account balance: 42.75 euros.
Input from the keyboard
To read a double, use the dedicated method of Scanner: console.nextDouble().
Scanner console = new Scanner(System.in);
System.out.println("Enter the temperature outside:");
double temperature = console.nextDouble(); // Read a double right away
System.out.println("Outside now: " + temperature + " degrees.");
4. The double type in action: arithmetic
All the usual operations (+, -, *, /) work just like for int:
double distance = 100.5;
double time = 2.0;
double speed = distance / time; // 50.25
System.out.println("Average speed: " + speed); // Average speed: 50.25
That’s all the arithmetic. The only difference: the result of division is always a floating-point number if at least one of the operands is double.
Compare with int
int a = 5, b = 2;
System.out.println(a / b); // 2 (remainder is discarded)
double aa = 5, bb = 2;
System.out.println(aa / bb); // 2.5
5. Typical mistakes and quirks when working with double
Input parsing error
A classic situation: the user enters 3,14 but the program expects 3.14. In Java, the Scanner.nextDouble() method is sensitive to the current locale: in Russian/German locales a comma is allowed, in English you need a dot. If necessary, configure the locale for Scanner or read a string and parse it manually.
// This will cause a problem in Locale.US if "3,14" is entered
double value = console.nextDouble();
The “inaccuracy” of numbers on a computer
This is where beginners usually get slightly puzzled:
double x = 0.1 + 0.2;
System.out.println(x); // Hm... 0.30000000000000004
Congratulations, you’ve encountered the “magic” of how floating-point numbers are represented inside a computer. The fact is, many numbers cannot be represented exactly in binary. This is usually not critical for most applications, but there are nuances in finance and the exact sciences.
6. Important: double and int — implicit and explicit conversion
Sometimes you add an integer and a floating-point value, or assign an int to a double variable—no errors will occur:
int i = 2;
double d = i; // All good!
System.out.println(d); // 2
double dd = 3.7;
int ii = (int) dd; // You must explicitly cast a double to int!
System.out.println(ii); // 3, the fractional part was truncated
This often surprises people—why did the fractional part disappear after casting? Simply because the int type cannot store fractions (everything after the dot is gone forever).
More about converting double to int and the (int) operator in the next lecture.
7. Formatted output: printing double nicely
By default, double is often printed with lots of extra digits. You can format the output:
double temp = 23.56789;
System.out.println(temp); // 23.56789
// 2 digits after the decimal
System.out.println(String.format("%.2f", temp)); // 23.57
// 1 digit after the decimal
System.out.println(String.format("%.1f%n", temp)); // 23.6
| Format | Result | Description |
|---|---|---|
|
23.57 | a number with 2 digits after the decimal point |
|
23.6 | a number with 1 digit after the decimal point |
8. Typical mistakes when working with float and double
Mistake #1: implicit conversion from double to float
float f = 1.23; // Error!
The compiler will complain: “You’re trying to put a double into a float—this can cause loss of precision!” Always add the f suffix.
Mistake #2: forgot that dividing two int values yields an int result
int a = 7, b = 2;
double result = a / b; // 3.0, not 3.5
To get the fractional part, explicitly cast at least one operand:
double result = (double) a / b; // 3.5
Mistake #3: comparing floating-point numbers
Do not compare floating-point numbers for equality using ==. Use comparison with a small tolerance (epsilon).
Mistake #4: loss of precision with float
Do not store large numbers or very precise values in float—they may “break” or lose important digits.
GO TO FULL VERSION