| Примитивный тип | Размер в памяти | Диапазон значений |
|---|---|---|
| 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, а как-то ведь надо объяснить компилятору, какое именно число мы хотим получить :)
Просто передать в конструктор число
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
не выйдет: 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); } }Вывод в консоль:
8198552921648689607min()и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.556ROUND_DOWN— отбрасывание разряда111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555ROUND_FLOOR— округление в меньшую сторону111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555ROUND_HALF_UP— округление в большую сторону, если число после запятой >= .50.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5ROUND_HALF_DOWN— округление в большую сторону, если число после запятой > .50.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6ROUND_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) -> ArithmeticExceptionROUND_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.
Это тот результат, на который мы и рассчитывали! :)
На этом наше сегодняшнее занятие окончено. Самое время вернуться к задачам! :)
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ