C 为什么以下两个阶乘尾随零的解不等价?

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

我正在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;
  }
  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也可能溢出。再次感谢您的耐心和富有洞察力的建议。当我第一次遇到这个问题时,我想到溢出可能会导致混乱的结果。但我检查了代码,但没有发现任何问题。所以我没有深入挖掘。嗯,我还有很多东西要学。:)