boolean
и char
, они делятся на такие типы:
- целые:
byte
,short
,int
иlong
; - с плавающей точкой (также называют вещественными числами):
float
иdouble
.
long
, с диапазоном от -9223372036854775808 до 9223372036854775807. Из чисел с плавающей точкой — double
, с диапазоном от 1.7e-308 до 1.7e+308. Подробнее о вещественных числах можно почитать в этой статье. Но что если нам понадобится сохранять числа, которые превышают допустимый диапазон? В таком случае нам пригодятся BigInteger
и BigDecimal
.
BigInteger в Java
Класс JavaBigInteger
используется How аналог целочисленных значений произвольной длины, у которого нет ограничения в 64 битов, How например у long. При этом он потомок класса Number
, How и стандартные обертки для числовых простых типов — 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
Тут же мы видим создание такого an object BigInteger
с передачей в конструктор нашего значения, но в формате строки. Стоит отметить, что конструктор у него не один, а на все случаи жизни. Если простые типы не вмещают полный объем данных из BigInteger
, данные будут урезаны до диапазона этого примитивного типа. Но при этом есть аналоги этих методов (intValueExact()
, longValueExact()
и т. д.), с той только разницей, что если простой тип, в который идет преобразование, не вмещает диапазон данных, выбрасывается ArithmeticException.
Константы BigInteger
Для внутреннего пользования, у класса есть константы:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Это константные an objectы 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
-
получение рандомного числа с заданием количества битов, которое будет использовать полученное meaning:
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
. Как правило его применяют для работы с финансами instead of double
, так How он дает больше возможности настройки. Как и BigInteger
, BigDecimal
является потомком класса Number
и имеет методы, возвращающие meaning an object в виде определенного примитивного типа:
BigDecimal value = new BigDecimal(35563.3);
long longValue = value.longValue();//35563
double doubleValue = value.doubleValue();//35563.3
Как мы можем видеть при приведении к long
, остаётся только целая часть, а знаки после запятой отбрасываются.
Конструкторы BigDecimal
С конструкторамиBigDecimal
мы ознакомимся подробнее, так How у класса есть их гораздо более широкий выбор. Есть конструкторы, позволяющие задать meaning an object разными способами (передачей int
, long
, double
, String
и даже BigInteger
), а есть такие, которые позволяю. задавать настройки создаваемого an object (способы округления, количество знаков после запятой):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Тут всё понятно, мы непосредственно задали meaning и количество знаков после запятой, которые хотим видеть.
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
Задаем массив знаков, с которого element берём значения для an object и сколько этих элементов берём.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Берем уже существующий an object BigInteger
, задаём Howое количество знаков после запятой.
Методы BigDecimal
КлассBigDecimal
также содержит в себе методы для разнообразных арифметических операций, но методов работы с битами, How у 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
Если же у нас в вещественной части все нули и в целой тоже есть (or у нас и вовсе нет знаков после запятой), тогда:
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
Для рассматриваемого значения это ближайшее число с урезанным знаком после запятой будем рассматривать How ближайшего соседа рассматриваемого числа. Например, 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
То округление идёт в большую сторону, так How последняя 5 смотрит на предыдущее meaning и видит нечётное число. Как следствие, число округляется в большую сторону до 6, после чего следующая 6 тоже идёт на округление. Но шестерка уже не смотрит на число слева, так How число явно ближе в большую сторону, и в итоге последняя 2 увеличивается на 1. ROUND_UNNECESSARY
— используется для проверки, что число в округлении не нуждается. То есть, мы проверяем, что число имеет нужное нам количество знаков после запятой:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult = firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Тут всё хорошо, meaning имеет два знака и мы проверяем, что после запятой только два знака. Но если:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
То мы получим — ArithmeticException
, так How проверяемое meaning превышает заданное количество знаков после запятой. Но если мы будем проверять два знака после запятой, а по факту там есть один, то исключение не выпадет, а недостающие знаки просто дополняются нулями:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY );//2.500
Еще хотелось бы отметить что у BigDecimal
есть константы, аналогичные константам BigInteger ZERO
, ONE
и TEN
. Вот link на documentацию. И напоследок: How вы, наверное, заметor, выполняя операции с an objectми BigInteger
и BigDecimal
, мы не изменяем старые, а всегда получаем новые. Это нам говорит о том, что они — immutable
, то есть неизменные после их создания, How и String
. Иными словами, все их методы не могут изменить внутреннее состояние an object, максимум — вернуть новый an object с параметрами, заданными используемой нами функцией.
GO TO FULL VERSION