1. Дробові числа
Припустімо, ви вирішили написати найпростіший калькулятор. Або будь‑яку іншу програму, де потрібні обчислення (від банального підрахунку грошей до складної фізики). Далеко не все в реальному житті — ціле число, і з цим нічого не вдієш!
Озброїмося новим типом даних!
У програмуванні дробові числа ще називають дійсними або числами з плаваючою комою (floating-point). У Java, як і в більшості мов, їх використовують для зберігання не лише цілих, а й «дробових» значень: на кшталт 3.14, -28.57, 2.718281828…
Дійсні числа мають два основні типи:
| Тип | Зберігає | Діапазон значень (приблизно) | Точність | Типовий розмір |
|---|---|---|---|---|
|
Числа | ±1.5 × 10-45 … ±3.4 × 1038 | ~7 знаків після крапки | 4 байти |
|
Числа | ±5.0 × 10-324 … ±1.7 × 10308 | ~15–16 знаків після крапки | 8 байтів |
Тип float
Тип float походить від поняття floating-point number — «число з плаваючою комою». У математиці дійсні числа мають певні властивості, натомість компʼютер має чимало обмежень. Тож не зовсім коректно називати дробові числа в Java дійсними — для них уживають назву «числа з плаваючою комою».
Тип float зазвичай зберігає 7 значущих цифр (наприклад, 0.1234567), показник ступеня десятки та займає 4 байти в памʼяті. Цього дуже мало для точних обчислень, тож усі швидко перейшли на числа подвійної точності.
Тип double
Назва типу double походить від «подвійна точність» (double). Він займає в памʼяті 8 байтів (удвічі більше, ніж float) і може зберігати до 15 значущих цифр: 0.123456789012345. Цього більш ніж достатньо для більшості обчислень із дробовими числами, тому double є основним типом для зберігання дробових чисел у Java.
У цій лекції зосередимося на типі double: його рекомендують використовувати за замовчуванням для всіх «звичайних» дробових чисел. Втім, далі розглянемо й тип float.
2. Оголошення й ініціалізація змінних типу double
Усе, як і з int — лише тепер використовуємо double.
// Оголошуємо змінну й присвоюємо їй значення Пі
double pi = 3.1415926;
// Можна оголосити й без ініціалізації
double averageSalary;
averageSalary = 91234.56;
// Можна обчислювати!
double pizzaPieces = 8;
double friends = 3;
double piecesPerFriend = pizzaPieces / friends; // 2.666… (а не 2)
Особливості синтаксису:
- Як десятковий роздільник використовується крапка (3.14). Якщо використаєте кому — отримаєте помилку компіляції!
- Точніше, записавши double d = 3;, ви не отримаєте помилку — відбудеться автоматичне перетворення типів (ціле число перетворюється на «дійсне» без втрат).
3. Введення й виведення дійсних чисел за допомогою Scanner
Спершу спробуємо вивести дробове число:
double amount = 42.75;
System.out.println(amount); // Виведе: 42.75
Усе гаразд! А якщо додати текст:
System.out.println("На вашому рахунку: " + amount + " євро."); // На вашому рахунку: 42.75 євро.
Введення з клавіатури
Для введення double потрібно використовувати спеціальний метод класу Scanner: console.nextDouble().
Scanner console = new Scanner(System.in);
System.out.println("Введіть температуру за вікном:");
double temperature = console.nextDouble(); // Одразу вводимо double
System.out.println("Зараз надворі: " + temperature + " градусів.");
4. Тип double у дії: арифметика
Усі звичні операції (+, -, *, /) працюють так само, як і для int:
double distance = 100.5;
double time = 2.0;
double speed = distance / time; // 50.25
System.out.println("Середня швидкість: " + speed); // Середня швидкість: 50.25
Ось і вся арифметика. Єдина відмінність: результат ділення — завжди дробове число, якщо хоча б один із операндів — double.
Порівняємо з int
int a = 5, b = 2;
System.out.println(a / b); // 2 (залишок відкидається)
double aa = 5, bb = 2;
System.out.println(aa / bb); // 2.5
5. Типові помилки та «дивини» під час роботи з double
Помилка під час перетворення введених даних
Класична ситуація: користувач вводить 3,14, а програма очікує 3.14. У Java метод Scanner.nextDouble() орієнтується на поточну локаль: у німецькій локалі кома допустима, в англійській — потрібна крапка. За потреби налаштуйте локаль для Scanner або прочитайте рядок і розберіть його вручну.
// Це спричинить проблему в Locale.US, якщо введено «3,14»
double value = console.nextDouble();
«Неточність» чисел у компʼютері
Ось тут у новачків зазвичай починається легке здивування:
double x = 0.1 + 0.2;
System.out.println(x); // Гм… 0.30000000000000004
Вітаю, ви зіткнулися з «магією» подання дробових чисел усередині компʼютера. Річ у тому, що багато чисел неможливо точно подати у двійковій системі. Зазвичай це не критично для більшості застосунків, але є нюанси у фінансах і точних науках.
6. Важливо: double і int — автоматичне та явне перетворення
Буває, ви додаєте ціле до дробового або присвоюєте int змінній double — помилок не буде:
int i = 2;
double d = i; // Усе гаразд!
System.out.println(d); // 2
double dd = 3.7;
int ii = (int) dd; // Потрібно явно перетворити тип double на тип int!
System.out.println(ii); // 3, дробова частина відкинулася
Часто це дивує: чому після перетворення дробова частина зникла? Просто тому, що тип int не вміє зберігати дроби (усе, що після крапки, зникло назавжди).
Детальніше про перетворення double у int і оператор (int) — у наступній лекції.
7. Форматоване виведення: красиво виводимо double
Часто за замовчуванням double виводиться з надлишком нулів. Можна відформатувати виведення:
double temp = 23.56789;
System.out.println(temp); // 23.56789
// 2 знаки після крапки
System.out.println(String.format("%.2f", temp)); // 23.57
// 1 знак після крапки
System.out.println(String.format("%.1f%n", temp)); // 23.6
| Формат | Результат | Опис |
|---|---|---|
|
23.57 | число з 2 знаками після крапки |
|
23.6 | число з 1 знаком після крапки |
8. Типові помилки під час роботи з float і double
Помилка № 1: неявне перетворення double у float
float f = 1.23; // Помилка!
Компілятор видасть помилку: «Ви намагаєтеся присвоїти double змінній float — це може призвести до втрати точності!» Завжди додавайте суфікс f.
Помилка № 2: забули, що ділення двох int дає цілочисельний результат
int a = 7, b = 2;
double result = a / b; // 3.0, а не 3.5
Щоб отримати дробову частину, явно перетворіть принаймні один операнд:
double result = (double) a / b; // 3.5
Помилка № 3: порівняння дробових чисел
Не порівнюйте дробові числа на рівність за допомогою ==. Використовуйте порівняння з невеликим допуском (epsilon).
Помилка № 4: втрата точності у float
Не зберігайте великі числа або дуже точні значення у типі float — вони можуть спотворитися або «втратити» важливі цифри.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ