C 为什么以下两个阶乘尾随零的解不等价?
我正在OJ网站上研究阶乘尾随零问题。我用谷歌搜索了这个问题,找到了一些解决方案:C 为什么以下两个阶乘尾随零的解不等价?,c,algorithm,C,Algorithm,我正在OJ网站上研究阶乘尾随零问题。我用谷歌搜索了这个问题,找到了一些解决方案: int solution1(int n) { int result = 0; while (n > 0) { result += n /= 5; } return result; } int solution2(int n) { int result = 0; for (int i = 5;n >= i; i *= 5) { result += n/i; }
int solution1(int n) {
int result = 0;
while (n > 0) {
result += n /= 5;
}
return result;
}
int solution2(int n) {
int result = 0;
for (int i = 5;n >= i; i *= 5) {
result += n/i;
}
return result;
}
尽管实施过程中有很多细节,但我认为基本原理是相同的,这是可以找到的。因此我假设这两个解是等价的。但当我提交它们时,结果证明solution2通过了502个测试用例中的500个,并在n=1808548329时得到了错误的答案(结果=452137080),而solution1得到了正确的答案(结果=452137076)
现在我不知道哪里出了问题。有人能告诉我为什么上面的两个解决方案不相等吗?为什么解决方案1是正确的而解决方案2是错误的?因为
i*=5
会溢出。当它溢出时,您将无法再与n
进行正确的比较
假设n=1808548329。下面是发生的情况:
i n correct i
----------- ---------- ------------
5 1808548329 5
25 1808548329 25
125 1808548329 125
625 1808548329 625
3125 1808548329 3125
15625 1808548329 15625
78125 1808548329 78125
390625 1808548329 390625
1953125 1808548329 1953125
9765625 1808548329 9765625
48828125 1808548329 48828125
244140625 1808548329 244140625
1220703125 1808548329 1220703125
1808548329 1808548329 6103515625 # i overflows here; loop should stop
452807053 1808548329 30517578125
-2030932031 1808548329 152587890625
-1564725563 1808548329 762939453125
766306777 1808548329 3814697265625
-463433411 1808548329 19073486328125
1977800241 1808548329 95367431640625
我通过以下方式生成了上述内容:
#include <stdio.h>
int main() {
int n = 1808548329;
int i = 1;
long long l = 1;
do {
i *= 5;
l *= 5;
printf("%14d %14d %14lld\n", i, n, l);
} while (n >= i);
return 0;
}
#包括
int main(){
int n=1808548329;
int i=1;
长l=1;
做{
i*=5;
l*=5;
printf(“%14d%14d%14lld\n”,i,n,l);
}而(n>=i);
返回0;
}
(在原始代码中,一些
n/i
值将是负数,只是为了使情况更加混乱。我没有包含n/i
列;这样做可能会很有趣。)我认为solution1不正确,因为它包含无限循环。很抱歉键入错误。解决方案1中的while循环应为结果+=n/=5;谢谢。根据你得到的答案,我猜第二个函数中的I
是无符号的。(或者可能是32位平台上的size\u t
)“输入错误”?你为什么不回避/粘贴它?谢谢你的回答。@AllenWang:事实上,5的溢出能力正是这个测试用例,这表明无论是谁设计了这个测试,他心里都有这个错误。人们可以从这个问题中学到一些东西,但这些东西都与最初的问题没有多大关系。其中之一是,你在谷歌搜索中发现的很多代码实际上都有细微的缺陷,所以不应该依赖它。另一个原因是,除了简单的递增1之外,任何形式的for循环都是可疑的;如果限制为INTMAX,即使增加1也可能溢出。再次感谢您的耐心和富有洞察力的建议。当我第一次遇到这个问题时,我想到溢出可能会导致混乱的结果。但我检查了代码,但没有发现任何问题。所以我没有深入挖掘。嗯,我还有很多东西要学。:)