Java Language
BigDecimal
Поиск…
Вступление
Класс BigDecimal предоставляет операции для арифметики (добавление, вычитание, умножение, деление), масштабирование, округление, сравнение, хэширование и преобразование формата. BigDecimal представляет собой неизменяемые десятичные числа с произвольной точностью. Этот класс должен использоваться при необходимости высокоточного вычисления.
Объекты BigDecimal являются неизменяемыми
Если вы хотите рассчитать с помощью BigDecimal, вы должны использовать возвращаемое значение, потому что объекты BigDecimal являются неизменяемыми:
BigDecimal a = new BigDecimal("42.23");
BigDecimal b = new BigDecimal("10.001");
a.add(b); // a will still be 42.23
BigDecimal c = a.add(b); // c will be 52.231
Сравнение BigDecimals
Метод compareTo
должен использоваться для сравнения BigDecimals
:
BigDecimal a = new BigDecimal(5);
a.compareTo(new BigDecimal(0)); // a is greater, returns 1
a.compareTo(new BigDecimal(5)); // a is equal, returns 0
a.compareTo(new BigDecimal(10)); // a is less, returns -1
Обычно вы не должны использовать метод equals
поскольку он считает, что два BigDecimals
равны, только если они равны по стоимости и также масштабируются :
BigDecimal a = new BigDecimal(5);
a.equals(new BigDecimal(5)); // value and scale are equal, returns true
a.equals(new BigDecimal(5.00)); // value is equal but scale is not, returns false
Математические операции с BigDecimal
В этом примере показано, как выполнять основные математические операции с помощью BigDecimals.
1.Addition
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a + b
BigDecimal result = a.add(b);
System.out.println(result);
Результат: 12
2.Subtraction
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a - b
BigDecimal result = a.subtract(b);
System.out.println(result);
Результат: 2
3.Multiplication
При умножении двух BigDecimal
s результат будет иметь масштаб, равный сумме шкал операндов.
BigDecimal a = new BigDecimal("5.11");
BigDecimal b = new BigDecimal("7.221");
//Equivalent to result = a * b
BigDecimal result = a.multiply(b);
System.out.println(result);
Результат: 36.89931
Чтобы изменить масштаб результата, используйте метод перегруженного множителя, который позволяет передавать MathContext
- объект, описывающий правила для операторов, в частности, режим точности и округления результата. Дополнительные сведения о доступных режимах округления см. В документации Oracle.
BigDecimal a = new BigDecimal("5.11");
BigDecimal b = new BigDecimal("7.221");
MathContext returnRules = new MathContext(4, RoundingMode.HALF_DOWN);
//Equivalent to result = a * b
BigDecimal result = a.multiply(b, returnRules);
System.out.println(result);
Результат: 36.90
4.Division
Разделение немного сложнее, чем другие арифметические операции, например, рассмотрим приведенный ниже пример:
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
BigDecimal result = a.divide(b);
System.out.println(result);
Мы ожидаем, что это даст нечто похожее: 0.7142857142857143, но мы получим:
Результат: java.lang.ArithmeticException: Неограничивающее десятичное расширение; нет точного представимого десятичного результата.
Это будет отлично работать, когда результат будет завершающим десятичным, скажем, если бы я хотел разделить 5 на 2, но для тех чисел, которые при делении будут давать не заканчивающийся результат, мы получим ArithmeticException
. В сценарии реального мира невозможно предсказать значения, которые будут встречаться во время деления, поэтому нам нужно указать масштаб и режим округления для деления BigDecimal. Для получения дополнительной информации о режиме масштабирования и округления см. Документацию Oracle .
Например, я мог бы сделать:
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a / b (Upto 10 Decimal places and Round HALF_UP)
BigDecimal result = a.divide(b,10,RoundingMode.HALF_UP);
System.out.println(result);
Результат: 0.7142857143
5.Remainder или модуль
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = a % b
BigDecimal result = a.remainder(b);
System.out.println(result);
Результат: 5
6.Power
BigDecimal a = new BigDecimal("5");
//Equivalent to result = a^10
BigDecimal result = a.pow(10);
System.out.println(result);
Результат: 9765625
7.Max
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = MAX(a,b)
BigDecimal result = a.max(b);
System.out.println(result);
Результат: 7
8.Min
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
//Equivalent to result = MIN(a,b)
BigDecimal result = a.min(b);
System.out.println(result);
Результат: 5
9. Переместите точку влево
BigDecimal a = new BigDecimal("5234.49843776");
//Moves the decimal point to 2 places left of current position
BigDecimal result = a.movePointLeft(2);
System.out.println(result);
Результат: 52.3449843776
10.Переведите точку вправо
BigDecimal a = new BigDecimal("5234.49843776");
//Moves the decimal point to 3 places right of current position
BigDecimal result = a.movePointRight(3);
System.out.println(result);
Результат: 5234498.43776
Существует множество дополнительных параметров и комбинаций параметров для вышеупомянутых примеров (например, существует 6 вариантов метода разделения), этот набор является неисчерпывающим списком и охватывает несколько базовых примеров.
Использование BigDecimal вместо float
В связи с тем, что тип float представлен в памяти компьютера, результаты операций с использованием этого типа могут быть неточными - некоторые значения сохраняются в виде приближений. Хорошими примерами этого являются денежные расчеты. Если требуется высокая точность, следует использовать другие типы. например, Java 7 предоставляет BigDecimal.
import java.math.BigDecimal;
public class FloatTest {
public static void main(String[] args) {
float accountBalance = 10000.00f;
System.out.println("Operations using float:");
System.out.println("1000 operations for 1.99");
for(int i = 0; i<1000; i++){
accountBalance -= 1.99f;
}
System.out.println(String.format("Account balance after float operations: %f", accountBalance));
BigDecimal accountBalanceTwo = new BigDecimal("10000.00");
System.out.println("Operations using BigDecimal:");
System.out.println("1000 operations for 1.99");
BigDecimal operation = new BigDecimal("1.99");
for(int i = 0; i<1000; i++){
accountBalanceTwo = accountBalanceTwo.subtract(operation);
}
System.out.println(String.format("Account balance after BigDecimal operations: %f", accountBalanceTwo));
}
Вывод этой программы:
Operations using float:
1000 operations for 1.99
Account balance after float operations: 8009,765625
Operations using BigDecimal:
1000 operations for 1.99
Account balance after BigDecimal operations: 8010,000000
Для стартового баланса 10000,00, после 1000 операций за 1.99, мы ожидаем, что баланс будет равен 8010,00. Использование типа float дает нам ответ около 8009,77, что неприемлемо неточно в случае денежных расчетов. Использование BigDecimal дает нам правильный результат.
BigDecimal.valueOf ()
Класс BigDecimal содержит внутренний кеш часто используемых чисел, например, от 0 до 10. Методы BigDecimal.valueOf () предоставляются в предпочтении конструкторам с похожими параметрами типа, то есть в приведенном ниже примере a предпочтительнее b.
BigDecimal a = BigDecimal.valueOf(10L); //Returns cached Object reference
BigDecimal b = new BigDecimal(10L); //Does not return cached Object reference
BigDecimal a = BigDecimal.valueOf(20L); //Does not return cached Object reference
BigDecimal b = new BigDecimal(20L); //Does not return cached Object reference
BigDecimal a = BigDecimal.valueOf(15.15); //Preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double)
BigDecimal b = new BigDecimal(15.15); //Return unpredictable result
Инициализация BigDecimals со значением нуля, один или десять
BigDecimal предоставляет статические свойства для чисел 0, один и десять. Рекомендуется использовать их вместо использования фактических чисел:
Используя статические свойства, вы избегаете ненужного создания экземпляра, также у вас есть буквальный код, а не «магическое число».
//Bad example:
BigDecimal bad0 = new BigDecimal(0);
BigDecimal bad1 = new BigDecimal(1);
BigDecimal bad10 = new BigDecimal(10);
//Good Example:
BigDecimal good0 = BigDecimal.ZERO;
BigDecimal good1 = BigDecimal.ONE;
BigDecimal good10 = BigDecimal.TEN;