Разделение 2 bigdecimals с точностью 0 и режимом округления HALF_UP [дубликат]

  @ElementCollection (fetch = FetchType.LAZY) @CollectionTable (name = "raw_events_custom", joinColumns = @JoinColumn (name = "raw_event_id")) @MapKeyColumn (name = "field_key", length = 50) @  Столбец (name = "field_val", length = 100) @BatchSize (size = 20) private Map & lt; String, String & gt;  customValues ​​= new HashMap & lt; String, String & gt; ();   

Это пример того, как настроить карту с контролем над именами столбцов и таблиц и длиной поля.

409
задан adelarsq 9 March 2013 в 14:19
поделиться

9 ответов

Из документов Java 5 (Java 8 docs здесь ):

Когда объект MathContext поставляется с настройкой точности 0 (например, MathContext.UNLIMITED), арифметические операции точны, а также арифметические методы, которые не принимают объект MathContext. (Это единственное поведение, которое поддерживалось в версиях до 5.)

. В качестве следствия вычисления точного результата настройка режима округления объекта MathContext с точностью 0 не используется и таким образом, не имеет значения. В случае деления точное частное может иметь бесконечно длинное десятичное разложение; например, 1 делится на 3.

Если фактор имеет бесконечное десятичное расширение и операция указана для возврата точного результата, генерируется исключение ArithmeticException. В противном случае возвращается точный результат деления, как это сделано для других операций.

Чтобы исправить, вам нужно сделать что-то вроде этого:

a.divide(b, 2, RoundingMode.HALF_UP)

where 2 is precision and RoundingMode.HALF_UP is rounding mode

Подробнее подробности: http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/

685
ответ дан Behrang 16 August 2018 в 11:54
поделиться

У меня была такая же проблема, потому что моя строка кода была:

txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");

Я перехожу к этому, читая предыдущий ответ, потому что я не писал десятичную точность:

txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");

4 - Десятичная точность

И RoundingMode являются константами Enum, вы можете выбрать любой из этих UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

. В этом случае HALF_UP будет иметь следующий результат:

2.4 = 2   
2.5 = 3   
2.7 = 3

Вы можете проверить информацию RoundingMode здесь: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

6
ответ дан Alex Montenegro1987 16 August 2018 в 11:54
поделиться

Ответа на этот вопрос по BigDecimal throws ArithmeticException

public static void main(String[] args) {
        int age = 30;
        BigDecimal retireMentFund = new BigDecimal("10000.00");
        retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
        BigDecimal yearsInRetirement = new BigDecimal("20.00");
        String name = " Dennis";
        for ( int i = age; i <=65; i++){
            recalculate(retireMentFund,new BigDecimal("0.10"));
        }
        BigDecimal monthlyPension =   retireMentFund.divide(
                yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));      
        System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
    }
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
        fundAmount.multiply(rate.add(new BigDecimal("1.00")));
    }

Добавить объект MathContext в ваш метод разбора и настроить точность и округление. Это должно решить вашу проблему

1
ответ дан Community 16 August 2018 в 11:54
поделиться

Потому что вы не указали точность и округление. BigDecimal жалуется, что он может использовать десятичные числа 10, 20, 5000 или бесконечность, и он все равно не сможет дать вам точное представление числа. Таким образом, вместо того, чтобы давать вам неправильный BigDecimal, он просто визжит на вас.

Однако, если вы предоставите RoundingMode и точность, то он сможет конвертировать (например, 1.333333333-to-infinity в нечто например, 1.3333 ... но вам, как программисту, нужно сказать, какую точность вы «довольны».

70
ответ дан David Bullock 16 August 2018 в 11:54
поделиться

Вы можете сделать

a.divide(b, MathContext.DECIMAL128)

Вы можете выбрать количество бит, которое вы хотите либо 32,64,128.

Проверьте эту ссылку:

http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=java6&state=class&package=java.math&class=MathContext

43
ответ дан DVK 16 August 2018 в 11:54
поделиться

Это вопрос округления результата, решение для меня следующее.

divider.divide(dividend,RoundingMode.HALF_UP);
0
ответ дан Jorge Santos Neill 16 August 2018 в 11:54
поделиться

Для исправления такой проблемы я использовал ниже код

a.divide(b, 2, RoundingMode.HALF_EVEN)

2 - точность. Теперь проблема решена.

11
ответ дан Martin Serrano 16 August 2018 в 11:54
поделиться

Ваша программа не знает, какую точность использовать десятичные числа, чтобы она выдавала:

java.lang.ArithmeticException: Non-terminating decimal expansion

Решение об исключении:

MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17
0
ответ дан Miloš Ojdanić 16 August 2018 в 11:54
поделиться

Это потому, что Bigdecimal не потерян, и если вы разделите 1/3, например, это приведет к повторению десятичной до бесконечности. 0.33333333 ... теоретически, если вы умножаете назад, вы получаете точный результат. Но число бесконечности будет генерировать стек над потоком, и в этом случае исключение запускается.

Мое решение:

 try {
     result = n1.divide(n2);
 } catch (ArithmeticException e){
     Log.d("Error bigdecimal", e.toString());
     result = (n1.doubleValue() / n2.doubleValue());
 };

, в этом случае ваш результат не будет сокращен Rounding

0
ответ дан Visruth 16 August 2018 в 11:54
поделиться
  • 1
    Это «гамбиарра». Используйте решение RoundingMode. – Willian Crozeta 6 June 2017 в 14:29
Другие вопросы по тегам:

Похожие вопросы: