boolean
і char
, вони поділяються на такі типи:
- цілі:
byte
,short
,int
іlong
; - з плаваючою точкою (також називають речовими числами):
float
іdouble
.
long
, з діапазоном від -9223372036854775808 до 9223372036854775807. З чисел з плаваючою точкою — double
, з діапазоном від 1.7e-308 до 1.7e+308. Докладніше про речові числа можна почитати в цій статті . Але якщо нам знадобиться зберігати числа, які перевищують допустимий діапазон? У такому разі нам знадобляться BigInteger
і BigDecimal
.
BigInteger в Java
Клас JavaBigInteger
використовується як аналог цілісних значень довільної довжини, який не має обмеження в 64 бітів, як наприклад у long. При цьому він нащадок класу Number
, як і стандартні обгортки для числових простих типів - Integer
, Long
, Byte
, Double
і так далі - тому має реалізації методів, що призводять до простих типів:
BigInteger value = new BigInteger("32145");
int intValue = value.intValue();//32145
long longValue = value.longValue();//32145
double doubleValue = value.doubleValue();//32145.0
Тут ми бачимо створення такого об'єкта BigInteger
з передачею в конструктор нашого значення, але у форматі рядка. Конструктор у нього не один, а на всі випадки життя. Якщо прості типи не містять повний обсяг даних з BigInteger
, дані будуть урізані до діапазону цього примітивного типу. Але при цьому є аналоги цих методів ( intValueExact()
, longValueExact()
і т. д.), з тією лише різницею, що якщо простий тип, в який йде перетворення, не містить діапазон даних, викидається ArithmeticException .
Константи BigInteger
Для внутрішнього користування клас має константи:BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Це константні об'єкти BigInteger
зі значеннями, відповідно, 0
, 1
і 10
.
Методи BigInteger
Однією з головних особливостей цього класу є повний методів, що реалізують стандартні арифметичні операції на Java. Наприклад:-
операції підсумовування:
BigInteger firstValue = new BigInteger("37995"); BigInteger secondValue = new BigInteger("35466"); BigInteger resultValue = firstValue.add(secondValue);//73461
-
операції множення:
BigInteger firstValue = new BigInteger("37995"); BigInteger secondValue = new BigInteger("35466"); BigInteger resultValue = firstValue.multiply(secondValue);//1347530670
-
операції знаходження залишку при розподілі одного числа на інше:
BigInteger firstValue = new BigInteger("37995"); BigInteger secondValue = new BigInteger("35466"); BigInteger resultValue = firstValue.remainder(secondValue);//2529
-
отримання абсолютного значення числа (тобто за модулем, без знака):
BigInteger firstValue = new BigInteger("-37995"); BigInteger resultValue = firstValue.abs();//37995
-
операції з обчисленням mod :
BigInteger firstValue = new BigInteger("-34"); BigInteger secondValue = new BigInteger("5"); BigInteger resultValue = firstValue.mod(secondValue); //1
-
отримання рандомного числа із завданням кількості бітів, яке використовуватиме отримане значення:
BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211 BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
-
операції побітових зрушень(this >> n)
Зрушення вліво:
BigInteger firstValue = new BigInteger("5"); BigInteger firstResultValue = firstValue.shiftLeft(3);//40
Зсув праворуч:
BigInteger secondValue = new BigInteger("34"); BigInteger secondResultValue = secondValue.shiftRight(2); //8
BigDecimal у Java
Коли нам потрібне дійсне число довільної довжини, використовується клас Java -BigDecimal
. Як правило його застосовують для роботи з фінансами замість double
того, що він дає більше можливості налаштування. Як і BigInteger
є BigDecimal
нащадком класу Number
і має методи, що повертають значення об'єкта у вигляді певного примітивного типу:
BigDecimal value = new BigDecimal(35563.3);
long longValue = value.longValue();//35563
double doubleValue = value.doubleValue();//35563.3
Як ми можемо бачити при наведенні до long
, залишається лише ціла частина, а знаки після коми відкидаються.
Конструктори BigDecimal
З конструкторамиBigDecimal
ми ознайомимося докладніше, оскільки клас має їх набагато ширший вибір. Є конструктори, дозволяють задати значення об'єкта різними способами (передачею int
, long
, double
, String
і навіть BigInteger
), а є такі, які дозволяю. задавати налаштування створюваного об'єкта (способи округлення, кількість знаків після коми):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Тут все зрозуміло, ми безпосередньо задали значення та кількість знаків після коми, які хочемо бачити.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
Результати цього конструктора можуть бути непередбачуваними, адже ми задаємо double, який за своєю природою дуже неоднозначний тип. Тому зазвичай рекомендується використовувати у конструкторі String
.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
Ми задаємо double
, але при цьому і задаємо параметр, який описує правило округлення (який містить кількість знаків після коми та алгоритм для округлення).
char[] arr = new String("455656.545").toCharArray();
BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
Задаємо масив знаків, з якого елемента беремо значення об'єкта і скільки цих елементів беремо.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Беремо вже існуючий об'єкт BigInteger
, задаємо якусь кількість знаків після коми.
Методи BigDecimal
КласBigDecimal
також містить у собі методи для різноманітних арифметичних операцій, але методів роботи з бітами, як у BigInteger
, у нього немає. Проте головна фішка BigDecimal
— гнучкість у роботі з числами з плаваючою комою. Давайте розглянемо деякі методи, які дають нам можливість панувати над речовими числами:
-
отримуємо точність (кількість чисел):
BigDecimal value = new BigDecimal("454334.34334"); int result = value.precision();//11
-
задаємо кількість знаків після коми та правило округлення:
BigDecimal firstValue = new BigDecimal(3445.544445); BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545
Дещо нижче ми розглянемо докладніше константи для завдання правил округлення.
-
ділимо
BigDecimal
на іншийBigDecimal
, при цьому вказуючи необхідну кількість знаків після коми і правило округлення:BigDecimal firstValue = new BigDecimal("455656.545"); BigDecimal secondValue = new BigDecimal(3445.544445); BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
-
переміщення комою вправо/ліворуч на певну кількість знаків:
BigDecimal value = new BigDecimal("455656.545"); BigDecimal firstResult = value.movePointRight (2);//45565654.5 BigDecimal secondResult = value.movePointLeft (2);//4556.56545
-
обрізаємо кінцеві нулі:
BigDecimal value = new BigDecimal("45056.5000"); BigDecimal result = value.stripTrailingZeros();//45056.5
Якщо ж у нас у речовій частині всі нулі і в цілій теж є (або у нас зовсім немає знаків після коми), тоді:
BigDecimal value = new BigDecimal("450000.000"); BigDecimal result = value.stripTrailingZeros();//4.5E+5
Правила округлення BigDecimal
Для завдання правил округлення, всерединіBigDecimal
ми можемо побачити спеціальні константи, що описують алгоритми округлення: ROUND_UP
- Заокруглення від нуля, округлення в бік речовинної частини:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN
- Округлення до нуля, тобто усічення речовинної частини:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_DOWN );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN );//-2.6
ROUND_CEILING
- Округлення до позитивної нескінченності. Тобто якщо число у нас позитивне, то -> ROUND_UP
, якщо негативне, то ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR
- Округлення до негативної нескінченності, тобто якщо число у нас позитивне, то -> ROUND_DOWN
, якщо негативне, то ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
Для значення, що розглядається, це найближче число з урізаним знаком після коми будемо розглядати як найближчого сусіда розглянутого числа. Наприклад, 2.43 буде ближче до 2.4, ніж до 2.5, але 2.48 буде ближче до 2.5. ROUND_HALF_DOWN
- Округлення до «найближчого сусіда». Якщо обидва сусіди рівновіддалені від конкретного значення, проводиться округлення до нуля. Рівновіддалені - це, наприклад, коли округлюване число - 5, і воно знаходиться на однаковій відстані від 0 і 10):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP
— режим округлення у бік «найближчого сусіда». Якщо обидва сусіди рівновіддалені, округлення виконується до більшого числа (це саме округлення, якому нас навчали в школі):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_HALF_UP );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP );//2.6
ROUND_HALF_EVEN
— округлення до «найближчого сусіда», якщо обидва сусіди не віддалені. У разі якщо перед округленим числом стоїть непарне, виконується округлення у більшу сторону, якщо парне — меншу:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
Такий результат ми отримуємо, тому що при округленні 5 дивиться на попереднє число 2, і бачачи, що воно парне округлення йде меншу сторону. Але якщо:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
Те округлення йде у бік, оскільки остання 5 дивиться на попереднє значення і бачить непарне число. Як наслідок, число округляється у велику сторону до 6, після чого наступна 6 теж йде на заокруглення. Але шістка вже не дивиться на число зліва, оскільки число явно ближче у велику сторону, і в результаті остання 2 збільшується на 1. ROUND_UNNECESSARY
- використовується для перевірки, що число округлення не потребує. Тобто, ми перевіряємо, що число має потрібну нам кількість знаків після коми:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult = firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Тут все добре, значення має два знаки і ми перевіряємо, що після коми лише два знаки. Але якщо:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Ми отримаємо — ArithmeticException
, оскільки перевірене значення перевищує задану кількість знаків після коми. Але якщо ми перевірятимемо два знаки після коми, а за фактом там є один, то виняток не випаде, а знаки, що бракують, просто доповнюються нулями:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY );//2.500
Ще хотілося б відзначити що BigDecimal
є константи, аналогічні константам BigInteger ZERO
, ONE
і TEN
. Ось посилання на документацію . І насамкінець: як ви, напевно, помітабо, виконуючи операції з об'єктами BigInteger
і BigDecimal
ми не змінюємо старі, а завжди отримуємо нові. Це нам говорить про те, що вони — immutable
тобто незмінні після їх створення, як і String
. Інакше кажучи, всі їх методи що неспроможні змінити внутрішній стан об'єкта, максимум — повернути новий об'єкт із параметрами, заданими використовуваної нами функцією.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ