[英]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 / base
和base
:
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
,這就是上面b
( OOPS
)的中間錯誤值。
另一方面,遞歸解僅使用連續減小的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.