递归collat​​z实现的意外错误

时间:2016-10-24 19:13:36

标签: c collatz

编辑:当我将代码上传到自动测试平台时程序不会崩溃 - 它会返回正确的结果,但需要的时间太长(超过5秒)... wtf ...

对于大学,我必须通过遵循collat​​z猜想来实现一个函数,该函数返回从输入到达1的步数。猜想非常简单 - 给定任何整数:

1。如果是偶数 - 除以2(n / 2)

2. 如果是奇数 - 乘以3并加一(n * 3 + 1)

猜想是所有数字最终都会达到1.我们不必证明或检查这一点,我们只需要返回给定数字所采取的步骤。

我们之前已经完成了这个问题,但这次我们必须检查更大的数字(它们指定使用long而不是int) AND 使用递归。他们给了我们骨架代码,并要求我们只实现函数 - 所以我的所有代码都包含在

int lengthCollat​​z(long n){// mycode}

main中的骨架代码收集两个输入值 - a和b,其中a&lt; b <100000000。它会检查a和b之间的每个数字,在collat​​z序列之后达到1,然后返回步数最多的数字。

我添加的功能似乎完全正常,但是在较大的值(当输入2为数百万时)时,它似乎无缘无故崩溃并且没有出错。我已经尝试将所有内容改为无条件的长篇甚至长篇大论以查看是否有东西溢出 - 在这种情况下程序就会卡住......我不明白什么是错的,请帮助我诊断错误。附:如何提高这些计算的速度?我们有5秒的限制。

我的所有代码都在lengthCollat​​z函数内(以及它上面的长度全局变量)你能识别问题吗?

#include <stdio.h>
#define MAX64 9223372036854775807L /* 2ˆ63 -1 */

int length = 0;

int lengthCollatz(long n) {
    length++;
    //if not 1
    if(n!=1){
        //if odd
        if(n&1) {
            lengthCollatz(n=n*3+1);
        }
        //if even
        else {
            lengthCollatz(n/=2);
        }

    }
    //if reached n = 1
    else {
        //return amount of steps taken
        int returnLength  = length;
        length = 0;
        return returnLength;
    }
}
int main(int argc, char *argv[])
{

int n, a, b, len=-1;

scanf ("%d %d", &a, &b);

while (a <= b) {

    int l = lengthCollatz(a);
        if (l > len) {
            n = a;
            len = l;
        }
        a++;
}
printf("%d\n", n);
return 0;
}

更新功能:

&#13;
&#13;
int lengthCollatz(long n) {
        if(n==1){
            //return depthRecursion;
        }
        else {
            if(n&1) {
                n=n*3+1;
            }
            else {
                n/=2;
            }
            return lengthCollatz(n);
        }
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

这是一个替代版本,它不会因OP给出的输入范围而出现段错误:

int collatz(unsigned long n)
{
    if (n == 1)
        return 1;
    else if (n & 1) 
        return 1 + collatz(n * 3 + 1);
    else
        return 1 + collatz(n >> 1);
}

AFAICT,它运作正常,但速度很慢。在平庸的PC上29秒。优化版本在结果可以预先计算时不调用自身,运行速度提高两秒,但该版本与手动循环展开相关。 FWIW:

int collatz(unsigned long n)
{
    if (n == 1)
        return 1;

    if (n & 1) 
        return 2 + collatz((n * 3 + 1) >> 1);

    // Is n dividable by 16?
    if (n & 0xF == 0)
        return 4 + collatz(n >> 4);

    // Is n dividable by 8?
    if (n & 0x7 == 0)
        return 3 + collatz(n >> 3);

    // Is n dividable by 4?
    if (n & 0x3 == 0)
        return 2 + collatz(n >> 2);

    return 1 + collatz(n >> 1);
}

当然有其他方法可以解决这个问题,但要在五秒内完成?如果找到解决方案,请发布解决方案。