簡體   English   中英

ArithmeticException:“非終止十進制擴展; 沒有精確的可表示的十進制結果”

[英]ArithmeticException: “Non-terminating decimal expansion; no exact representable decimal result”

為什么以下代碼會引發如下所示的異常?

BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.

例外:

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

來自Java 11 BigDecimal文檔

MathContext對象的精度設置為 0(例如MathContext.UNLIMITED )時,算術運算是精確的,不采用MathContext對象的算術方法也是如此。 (這是 5 之前的版本中唯一支持的行為。)

作為計算精確結果的必然結果,精度設置為 0 的MathContext對象的舍入模式設置未使用,因此無關緊要。 在除法的情況下,精確的商可以有無限長的十進制展開; 例如,1 除以 3。

如果商具有非終止的十進制擴展並且指定操作返回精確結果,則拋出ArithmeticException 否則,將返回除法的確切結果,就像其他操作一樣。

要修復,您需要執行以下操作

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

其中 2 是比例和 RoundingMode.HALF_UP 是舍入模式

有關更多詳細信息,請參閱此博客文章

因為您沒有指定精度和舍入模式。 BigDecimal 抱怨它可以使用 10、20、5000 或無窮大小數位,但它仍然無法為您提供數字的精確表示。 因此,它不會為您提供不正確的 BigDecimal,而是只會對您發牢騷。

但是,如果您提供 RoundingMode 和精度,那么它將能夠轉換(例如 1.333333333 到無窮大到 1.3333 之類的東西……但是作為程序員,您需要告訴它您對什么精度感到滿意'。

你可以做

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

為了解決這樣的問題,我使用了下面的代碼

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

二是精准。 現在問題解決了。

我有同樣的問題,因為我的代碼行是:

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

我改為這個,閱讀以前的答案,因為我沒有寫小數精度:

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

4 是十進制精度

AND 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/

這是一個舍入結果的問題,我的解決方案如下。

divider.divide(dividend,RoundingMode.HALF_UP);

BigDecimal 的答案拋出 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 對象並調整精度和舍入模式。 這應該可以解決您的問題

您的程序不知道要使用的十進制數的精度是多少,因此它會拋出:

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

這是因為Bigdecimal不會丟失,例如,如果將1/3除,則將導致重復的十進制到無窮大。 0.33333333 ...從理論上講,如果再相乘,您將得到准確的結果。 但是,無窮大數將生成堆棧溢出,在這種情況下,將引發異常。

一個辦法:

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

要么

n1.divide(n2,RoundingMode.HALF_UP);

在這種情況下,您的結果將不會被舍入

對我來說,它正在處理這個:

BigDecimal a = new BigDecimal("9999999999.6666",precision);
BigDecimal b = new BigDecimal("21",precision);

a.divideToIntegralValue(b).setScale(2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM