Поиск…


Вступление

Класс 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;


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow