在使用dotnetfiddle解决一些练习问题的过程中,我遇到了一些非常奇怪的事情。我有一个应用数学序列的程序(每个步骤的不同计算取决于当前步骤是偶数还是奇数):
using System;
public class Program
{
public static void Main()
{
int ceiling = 1000000;
int maxMoves = 0;
int maxStart = 0;
int testNumber;
for(int i = 1; i <= ceiling; i++){
testNumber = i;
int moves = 1;
while(testNumber != 1){
if(testNumber % 2 == 0){
testNumber = testNumber / 2;
moves++;
} else {
testNumber = (3 * testNumber) + 1;
moves++;
}
}
if(moves > maxMoves){
maxMoves = moves;
maxStart = i;
}
}
Console.WriteLine(maxStart);
Console.WriteLine(maxMoves);
}
}
如上所述,超出了执行时间限制。但是,如果我将测试编号的声明更改为long而不是int,则程序将运行:
int maxMoves = 0;
int maxStart = 0;
**long** testNumber;
为什么要进行此更改,这需要将i
从int
重新转换为long
for循环的每个增量(testNumber = i
),要比离开更快这是一个int
?是否在long
值上更快地执行数学运算?
答案 0 :(得分:6)
原因似乎是溢出。如果您运行包含在
中的代码checked
{
// your code
}
使用OverflowException
作为testNumber
时,您获得int
。
原因是最终3*testNumber+1
超出int
的边界。在unchecked
上下文中,这不会引发异常,但会导致testNumber
的否定值。
此时你的序列(我认为它是Collatz,对吗?)不再起作用,计算需要(可能无限期)更长,因为你永远不会达到1
(或至少需要你需要更多的迭代来达到1
)。