簡體   English   中英

發現階乘尾隨零時結果不一致

[英]inconsistent results when finding Factorial Trailing Zero

這是我編寫的兩個版本的代碼,用於返回n!中的尾隨零。 第一個版本返回452137080輸入1808548329 ,第二個版本返回452137076輸入1808548329 想知道為什么會有區別嗎? 第二版本的輸出正確。

Java源代碼

public class TrailingZero {
    public static int trailingZeroes(int n) {
        int result = 0;
        int base = 5;
        while (n/base > 0) {
            result += n/base;
            base *= 5;
        }

        return result;
    }

    public static int trailingZeroesV2(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroesV2(n / 5);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(trailingZeroes(1808548329));
        System.out.println(trailingZeroesV2(1808548329));
    }
}

這是由於base的值出現整數溢出

稍微更改代碼即可打印n / basebase

public class TrailingZero {
    public static int trailingZeroes(int n) {
        int result = 0;
        int base = 5;
        while (n/base > 0) {
            System.out.println("n = " + n/base  + " base = " + base);
            result += n/base;
            base *= 5;
        }

        return result;
    }

    public static int trailingZeroesV2(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroesV2(n / 5);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(trailingZeroes(1808548329));
        System.out.println(trailingZeroesV2(1808548329));
    }
}

輸出:

n = 361709665 base = 5
n = 72341933 base = 25
n = 14468386 base = 125
n = 2893677 base = 625
n = 578735 base = 3125
n = 115747 base = 15625
n = 23149 base = 78125
n = 4629 base = 390625
n = 925 base = 1953125
n = 185 base = 9765625
n = 37 base = 48828125
n = 7 base = 244140625
n = 1 base = 1220703125
n = 1 base = 1808548329   <== OOPS 6103515625 overflows 32-bit integer
n = 3 base = 452807053
452137080

如您1220703125 ,當n = 1時, base增加到1220703125然后運行語句base *= 5 ,使其6103515625 ,這比最大32位unsigned int( 2^32 )正好6103515625 - 2^32 = 1808548329 ,這就是上面bOOPS )的中間錯誤值。

另一方面,遞歸解僅使用連續減小的n值。 因此,沒有溢出。

簡單的解決方案是將base聲明為long,即long base = 5 這將返回正確的值452137076

另一個解決方案是將循環修改為僅使用n ,類似於遞歸解決方案:

    int base = 5;
    while (n > 0) {
        result += n/base;
        n = n/base;
    }

注意,在涉及階乘的問題中,溢出是給定的,您可能需要考慮使用諸如BigInteger之類的更高精度的算法。

暫無
暫無

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

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