Примітивний тип | Розмір у пам'яті | Діапазон значень |
---|---|---|
byte | 8 біт | від -128 до 127 |
short | 16 біт | до -32768 до 32767 |
char | 16 біт | від 0 до 65536 |
int | 32 біта | від -2147483648 до 2147483647 |
long | 64 біта | від -9223372036854775808 до 9223372036854775807 |
float | 32 біта | від (2 у ступені -149) до ((2-2 у ступені -23)*2 у ступені 127) |
double | 64 біта | від (-2 у ступені 63) до ((2 у ступені 63) - 1) |
boolean | 8 (при використанні в масивах), 32 (при використанні не в масивах) | true або false |
BigInteger
практично BigDecimal
нічим не обмежений. Навіщо використовуються ці класи? Насамперед для обчислень з вкрай високими вимогами до точності. Є, наприклад, програми, у яких від точності обчислень може залежати людське життя (ПЗ для літаків і ракет або медичного устаткування). Тому якщо навіть 150-й розряд після коми відіграє важливу роль,BigDecimal
- кращий вибір. Крім того, досить часто ці об'єкти застосовуються у світі фінансів, де точність обчислень аж до найменших значень теж є вкрай важливою. Як працювати з об'єктами BigInteger
та BigDecimal
що важливо про них пам'ятати? Об'єкти цих класів створюються так:
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
System.out.println(decimal);
}
}
Передача рядка як параметр — лише один із можливих конструкторів. Тут ми використовуємо рядки, тому що наші числа перевищують максимальні значення long
і double
, а якось треба пояснити компілятору, яке саме число ми хочемо отримати :) Просто передати в конструктор число 111111111111111111111111111111111111111111111111111111111111111111111111111111111 не вийде: Java спробує «вмістити» передане число в один із примітивних типів даних, але в жодне з них воно не влізе. Тому використання рядка передачі потрібного числа — хороший варіант. Обидва класи можуть автоматично витягувати з переданих рядків числові значення. Ще один важливий момент, який необхідно пам'ятати при роботі з класами великих чисел - їх об'єкти є незмінними ( Immutable
) . З принципом незмінності ти вже добре знайомий на прикладі класу String
та класів-оберток для примітивів (Integer, Long та іншими).
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
integer.add(BigInteger.valueOf(33333333));
System.out.println(integer);
}
}
Виведення в консоль:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Наше число не змінилося, як і слід очікувати. Щоб операція додавання пройшла успішно, необхідно створити новий об'єкт і присвоїти йому результат додавання.
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigInteger result = integer.add(BigInteger.valueOf(33333333));
System.out.println(result);
}
}
Виведення в консоль:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Ось тепер все працює як треба :) До речі, звернув увагу, як незвичайно виглядає операція складання?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Це ще один важливий момент. Класи великих чисел не використовують у своїй роботі оператори +-*/, а надають натомість набір методів. Давай ознайомимося з основними (повний перелік методів ти, як і завжди, можеш знайти в документації Oracle: тут і тут ).
-
Методи здійснення арифметичних операцій:
add()
,subtract()
,multiply()
,divide()
. Використовуються для операцій складання, віднімання, множення та поділу відповідно. -
doubleValue()
,intValue()
,floatValue()
,longValue()
і т.д. використовуються для перетворення великого числа до примітивного типу Java. Будь обережний при їх використанні та не забувай про різницю у місткості!import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); long result = integer.longValue(); System.out.println(result); } }
Виведення в консоль:
8198552921648689607
-
min()
і – дозволяють знайти мінімальне та максимальне значення з двох переданих великих чисел. Зверни увагу: методи не статичні!max()
import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); System.out.println(integer.max(integer2)); } }
Виведення в консоль:
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
Управління округленням BigDecimal
Ця тема винесена в окремий розділ, оскільки округлення великих чисел та його налаштування — річ не така проста. Ти можеш встановити кількість цифр після коми для числаBigDecimal
за допомогою методу setScale()
. Наприклад, ми хочемо встановити для числа 111.5555555555 точність три цифри після коми. Однак ми не зможемо передати число 3 як аргумент у метод setScale()
і таким чином вирішити наше завдання. Як було сказано вище, BigDecimal
це числа для обчислень з підвищеною точністю. У поточному вигляді наше число має 10 цифр після коми. Ми хочемо відкинути 7 їх і залишити лише 3. Тому крім числа 3 ми маємо передати як параметр режим округлення ( rounding mode ). Всього уBigDecimal
Існує 8 режимів округлення. Чимало! Але якщо тобі в програмі знадобиться справді тонке настроювання точності обчислень, тобі буде для цього все необхідне. Отже, ось які 8 режимів округлення є в BigDecimal
:
-
ROUND_CEILING
- Округлення у велику сторону111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
-
ROUND_DOWN
- відкидання розряду111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
-
ROUND_FLOOR
- Округлення в менший бік111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
-
ROUND_HALF_UP
— заокруглення у велику сторону, якщо число після коми >= .50.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
-
ROUND_HALF_DOWN
— округлення у велику сторону, якщо число після коми > .50.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
-
ROUND_HALF_EVEN
- Заокруглення залежатиме від цифри зліва від коми. Якщо цифра зліва буде парною, то округлення буде зроблено вниз, у бік. Якщо цифра ліворуч від коми непарна, то округлення буде зроблено вгору.2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
Цифра зліва від коми – 2 – парна. Округлення відбувається вниз. Оскільки нам потрібно 0 знаків після коми, результатом буде 2.
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
Цифра зліва від коми – 3 – непарна. Округлення відбувається вгору. Оскільки нам потрібно 0 знаків після коми, результатом буде 4.
-
ROUND_UNNECCESSARY
— використовується в тих випадках, коли якийсь метод потрібно передати режим округлення, але число округлення не потребує. Якщо спробувати зробити округлення числа при виставленому режимі ROUND_UNNECCESSARY — викинутий виняток ArithmeticException.3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
-
ROUND_UP
- Округлення у велику сторону.111.5551 -> setScale(3, ROUND_UP) -> 111.556
Порівняння великих чисел
Це питання також важливе. Ти вже пам'ятаєш, що для порівняння об'єктів Java використовується методequals()
. Він або надається самою мовою (у разі вбудованих Java класів), або перевизначається програмістом. Але у випадку з об'єктами класів BigDecimal
використовувати метод equals()
порівняння не рекомендується. Причина цього в тому, що метод BigDecimal.equals()
двох чисел повертає true тільки у випадку, якщо 2 числа мають однакове значення та масштаб (scale) : Давай порівняємо поведінку методів equals()
у Double
і BigDecimal
:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Double a = 1.5;
Double b = 1.50;
System.out.println(a.equals(b));
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.equals(y));
}
}
Виведення в консоль:
true
false
Як бачиш, числа 1.5 і 1.50 у випадку BigDecimal
виявабося нерівними! Це сталося саме через специфіку роботи методу equals()
, в класі BigDecimal
. Для більш коректного порівняння двох BigDecimal
краще використовувати метод compareTo()
:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.compareTo(y));
}
}
Виведення в консоль:
0
Метод compareTo()
повернув 0, що означає рівність 1.5 та 1.50. Це той результат, на який ми розраховували! :) На цьому наше сьогоднішнє заняття закінчено. Саме час повернутися до завдань! :)
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ