ArithmeticException: “Sonlandırmayan ondalık genişleme; kesin temsili ondalık sonuç yok ”


507

Aşağıdaki kod neden aşağıda gösterilen özel durumu oluşturuyor?

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

İstisna:

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

Yanıtlar:


843

Gönderen Java 11 BigDecimaldocs :

Bir MathContextnesneye duyarlılık ayarı 0 (örneğin, MathContext.UNLIMITED) sağlandığında, MathContextnesne almayan aritmetik yöntemler gibi aritmetik işlemler de doğrudur . (5'ten önceki sürümlerde desteklenen tek davranış budur.)

Kesin sonucu hesaplamanın bir sonucu olarak, MathContexthassas ayar 0 olan bir nesnenin yuvarlama modu ayarı kullanılmaz ve bu nedenle önemsizdir. Bölme durumunda, kesin bölüm sonsuz uzunluğunda ondalık genişlemeye sahip olabilir; örneğin, 1 bölü 3.

Bölümde kesinti olmayan bir ondalık genişleme varsa ve işlemin kesin bir sonuç döndürmesi belirtilirse ArithmeticException, a atılır. Aksi takdirde, bölümün kesin sonucu, diğer işlemler için olduğu gibi döndürülür.

Düzeltmek için böyle bir şey yapmanız gerekir :

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

burada 2 ölçek ve RoundingMode.HALF_UP yuvarlama modudur

Daha fazla ayrıntı için bu blog yayınına bakın .


3
Bu jasper hatası için de çalışıyor teşekkürler community.jaspersoft.com/questions/528968/…
shareef

27
2 DEĞİL precision; öyle scale. Lütfen bkz docs.oracle.com/javase/7/docs/api/java/math/…
John Manko

(yeni BigDecimal (100)). bölme (yeni BigDecimal (0.90), 2, RoundingMode.HALF_UP)
egemen

@AnandVarkeyPhilips Ölçektir. Javadoc'a bakın . Düzenleme reddedildi.
Lorne Marquis

@ user207421, yanlışlıkla düzenledim ve geri almaya çalıştım .. Ancak bir düzenlemeyi silmek için yeterli puanım
Anand Varkey Philips

76

Çünkü bir hassasiyet ve yuvarlama modu belirtmiyorsunuz. BigDecimal, 10, 20, 5000 veya sonsuzluk ondalık basamakları kullanabileceğinden ve size sayının tam bir temsilini veremeyeceğinden şikayet ediyor. Size yanlış bir BigDecimal vermek yerine, sadece size sarılıyor.

Bununla birlikte, bir RoundingMode ve hassasiyet sağlarsanız, o zaman 1.3333 gibi bir şeye dönüştürebilir (örn. '.



13

Böyle bir sorunu düzeltmek için aşağıdaki kodu kullandım

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

2 hassastır. Şimdi sorun çözüldü.


3
koda ek olarak, bazı açıklamalar verilmelidir.
Martin Serrano

11
2 DEĞİL precision; öyle scale. Lütfen bkz docs.oracle.com/javase/7/docs/api/java/math/…
John Manko

3
Finansal uygulamalar için RoundingMode.HALF_EVEN önerilir. Bankacılıkta kullanılan şey bu
ACV

John Mankos'un hassasiyet hakkındaki yorumu ile karıştırılanlar için, lütfen bu cevaba bakınız stackoverflow.com/questions/4591206/…
Stimpson Cat

5

Kod satırım olduğu için aynı sorunu yaşadım:

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

Ben ondalık duyarlık yazmıyordu çünkü önceki Cevap okuma, bunu değiştirmek:

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

4 Ondalık Hassasiyet

AND RoundingMode, Enum sabitleridir, bunlardan herhangi birini seçebilirsiniz UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

Bu durumda HALF_UP, şu sonuca sahip olacaktır:

2.4 = 2   
2.5 = 3   
2.7 = 3

RoundingModeBilgileri buradan kontrol edebilirsiniz : http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/


4 ölçek değil, hassasiyet.
Lorne Marquis,

3

Sonucun yuvarlanması sorunu, benim için çözüm şudur.

divider.divide(dividend,RoundingMode.HALF_UP);

1

BigDecimal atar ArithmeticException için cevap

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")));
    }

Bölme yöntemi çağrınıza MathContext nesnesini ekleyin ve kesinlik ve yuvarlama modunu ayarlayın. Bu, sorununuzu çözmelidir


0

Programınız ondalık sayılar için hangi hassasiyeti kullanacağını bilmez, bu nedenle atar:

java.lang.ArithmeticException: Non-terminating decimal expansion

İstisnayı atlama çözümü:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.