【问题标题】:Why does changing int to long speed up the execution? [duplicate]为什么将 int 更改为 long 会加快执行速度? [复制]
【发布时间】:2016-02-09 21:18:47
【问题描述】:

我正在尝试解决problem #14 from Project Euler,并编写了以下C#...

int maxColl = 0;
int maxLen = 0;
for (int i = 2; i < 1000000; i++) {
  int coll = i;
  int len = 1;
  while (coll != 1) {
    if (coll % 2 == 0) {
      coll = coll / 2;
    } else {
      coll = 3 * coll + 1;
    }
    len++;
  }
  if (len > maxLen) {
    maxLen = len;
    maxColl = i;
  }
}

麻烦的是,它只是跑了又跑,似乎没有停止。

在搜索了其他人的解决方案后,我看到一个看起来非常相似,只是他使用了 long 而不是 int。我不明白为什么这是必要的,因为这个问题中涉及的所有数字都在 int 的范围内,但我还是尝试了。

将 int 更改为 long 使代码在 2 秒内运行。

谁能给我解释一下?

【问题讨论】:

  • 只是从 int 更改为 long 不应该有那么大的差异。我怀疑你有一个溢出来阻止 while 循环中断。在调试器中观察它,看看你是否无法确定某处是否存在溢出。
  • 通常 Int64 比 Int32 慢。您可能在这里进行了溢出处理,导致 Int32 变慢。
  • @Ben 它通常同样快,除了除法和一些复杂的操作。在某些以 32 位值运行的系统上甚至更慢,因为您需要符号/零扩展和掩码才能转换为 64 位值

标签: c#


【解决方案1】:

i等于113383时,3X+1序列在某一点超过了int的最大值,所以3 * coll + 1溢出变成负数:

113383 → 340150 → ... → 1654740898 → 827370449 → -1812855948 → -906427974 → ...

最终,序列以以下负数循环结束:

...→-17→-50→-25→-74→-37→-110→-55→-164→-82→-41→-122→-61→-182→-91→- 272→-136→-68→-34→-17

这个循环不包括 1,所以你的循环永远不会终止。

使用long 代替int 可确保coll 永远不会溢出。

【讨论】:

  • 啊!我以为我已经检查过了。解释了为什么我在其他一些问题上也遇到了类似的问题。
【解决方案2】:

您的整数溢出并变为负数。
因此,您的循环永远不会真正终止。
如果将代码包装在 checked 块中,则会看到溢出异常。

long 足够大,可以存储您需要的值,因此可以正常工作。

【讨论】:

  • 感谢您的解释。你的和迈克尔刘的同时进来,他的解释稍微多一点,所以我把他的作为答案,但你的也很有帮助。非常感谢。
  • @AvrohomYisroel 公平地说,SLaks 快了两分钟 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 2010-11-17
  • 2017-10-19
相关资源
最近更新 更多