簡體   English   中英

Java計算C(n,k)和biginteger階乘

[英]Java Compute C(n,k) and factorial with biginteger

我想計算C(n,k)的答案,例如C(10,2)= 10 * 9/2 * 1 = 45如果我用10這樣的小數測試我的代碼,則該代碼有效。 但是,當我嘗試計算C(1000,900)時,它會編譯

線程“主”中的異常java.lang.ArithmeticException:/零

我見過有人說應該使用BigInteger ,但是嘗試之后,它仍然有錯誤。

例如:我將int factorial更改為BigInteger factorial ,而cSelect的for循環則無法將int i更改為BigInteger類型,結果,答案up/factorial(y)出錯。

請幫助我解決此問題。 謝謝!!

public class Test {

    // Write a factorial function
    static int factorial(int m) {
        int result =1;
        for (int i=2; i<=m; i++) {
            result = result*i;
        }
        return result;
    }

    // Caculate C(x,y)
    static int cSelect(int x, int y) {
        int up=1;
        for(int i=x; i>=(x-y+1); i--) {
            up = up*i;
        }
        return up/factorial(y);
    }

    public static void main(String[] args) {
        System.out.println(cSelect(1000,900));

    }

}

您的代碼很容易轉換為factorial ONE開頭,為循環中的每個i乘以BigInteger.valueOf(long) 喜歡,

// Write a factorial function
static BigInteger factorial(int m) {
    BigInteger result = BigInteger.ONE;
    for (int i = 2; i <= m; i++) {
        result = result.multiply(BigInteger.valueOf(i));
    }
    return result;
}

您的其他函數的功能完全相同 ,再加上除因factorial(y)的結果。 喜歡,

// Caculate C(x,y)
static BigInteger cSelect(int x, int y) {
    BigInteger up = BigInteger.ONE;
    for (int i = x; i >= (x - y + 1); i--) {
        up = up.multiply(BigInteger.valueOf(i));
    }
    return up.divide(factorial(y));
}

沒有其他改變,我得到了

63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890

我認為是正確的。

您必須使用BigInteger進行計算。

您嘗試計算的值大約為6.385051192630516e + 139,並且不能表示為Java基本整數值。

即使結果可以表示,但除以零錯誤的原因是除數表達式900! ∗ 100! 900! ∗ 100! 溢出到零。 然后,您將其除以零。

它溢出到零的原因是它可以被2 ^ 32和2 ^ 64整除。 可以通過使用一些簡單的代數來計算900中2的因數的數量來證明! 和100!

首先,返回值必須為BigInteger ,因為C(1000,900)遠遠超出int的范圍。

其次,您不需要單獨的factorial()方法。 迭代時進行除法將通過不創建過大的中間值(以進行多次除法為代價,但實際上可能更快)來改善內存占用。

像這樣:

static BigInteger cSelect(int x, int y) {
    BigInteger v = BigInteger.ONE;
    for (int i = x, j = 1; j <= y; i--, j++)
        v = v.multiply(BigInteger.valueOf(i)).divide(BigInteger.valueOf(j));
    return v;
}

通過將i向下計數和j向上計數,除法將永遠不會占一小部分。

測試

System.out.println(cSelect(10, 2));
System.out.println(cSelect(1000, 900));

產量

45
63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890

暫無
暫無

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

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