根据Zeckendorf定理编码的斐波那契

时间:2017-10-21 15:52:14

标签: c algorithm output

有一个代码将x解释为由zeckendorf定理编码的斐波那契。问题是代码对所有输入值都有 NOT

示例

输入 - > 输出

3 - >的 100

4 - >的 101

7 - >的 1010

100 - >的 1000010100

然而,当我输入值 34639092 时,输出 101000010100101000000000100010011010 ,这是错误的答案(zeckendorf定理)。

正确的答案是 101000010100101000000000100010010010 ,它们几乎相似,但右侧4位没有“1”。调试代码时,您可以看到此“1”不得出现在错误的答案中。

我无法理解输出错误答案的原因。我怀疑代码中有错误。

#include <stdio.h>

int main()
{
    long count = -1;
    unsigned long a, b, k, x, supercount = 0,  sumc = 0;
    a = 0;
    b = 1;
    scanf ("%lu", &x);
    k = x;
    if (x == 0){
        printf("0");
    }
    for(;x > 0;){
        while ((k >= 0) && (a <= x-b)){
            a = a + b;
            b = a - b;
            k -= 1;
            count ++;
        }
        x -= a;
        sumc |= 1 << (count-1);
        b = 1;
        a = 0;
        count = -1;
    }
    unsigned long r = sumc;
    while (r != 0){
        r /= 2;
        supercount++;
    }
    int arr[supercount];
    for (int q = 0; q < supercount; q ++){
        if (sumc !=0 ){
            arr[q] = sumc % 2;
            sumc /= 2;
        }
    }
    for (int i = supercount-1; i >=0 ; i--){
        printf ("%d", arr[i]);
    }
}

1 个答案:

答案 0 :(得分:3)

问题似乎在这里:

        sumc |= 1 << (count-1);

假设编译器上的unsigned long转换为64位,它应该是:

        sumc |= (unsigned long)1 << (count-1);

将1位存储到arr中的备用版本。使用Visual Studio进行微小更改。

#include <stdio.h>
typedef unsigned long long uint64_t;
int main()
{
    int arr[96] = {0};  /* fib(93) is max fib() <= 2^64 */
    int count;
    uint64_t a, b, x, y, z;
    scanf("%llu", &x);  /* llu needed for 64 bit input for VS */
    if (x == 0){
        printf("0\n");
        return 0;
    }
    y = x;          /* save x */
    while(x != 0){
        count = 0;  /* count == 0 => fib(2) */
        a = 1;      /* fib(2) == fib(count+2) */
        b = 1;      /* fib(1) == fib(count+1) */
        /* find largest fib(count+2) < x */
        while (a <= x-b){
            count++;    /* count += 1 */
            a = a + b;  /* a = fib(count+2) */
            b = a - b;  /* b = fib(count+1) */
        }
        x -= a;     /* subtract fib(count+2) from x */
        arr[count] = 1;
    }
    count = sizeof(arr)/sizeof(arr[0]);
    while(arr[--count] == 0);
    while(count >= 0){
        printf ("%d", arr[count]);
        count--;
    }
    printf("\n");
    /* check result */
    z = 0;
    a = 1;      /* fib(1) */
    b = 0;      /* fib(0) */
    for(count = 0; count < sizeof(arr)/sizeof(arr[0]); count++){
        a = a + b;  /* a = fib(count+2) */
        b = a - b;  /* b = fib(count+1) */
        if(arr[count] != 0)
            z += a;
    }
    if(y != z)
        printf("mistmatch\n");
    return 0;
}

这个版本更快,因为它只使用一个循环来查找总计为x的所有Fibonacci项。

#include <stdio.h>
typedef unsigned long long uint64_t;
int main()
{
    int arr[96] = {0};  /* fib(93) is max fib() <= 2^64 */
    int count;
    uint64_t a, b, x, y, z;
    /* these could be calculated with a one time loop */
    a = 12200160415121876738ull;    /* fib(93) */
    b = 7540113804746346429ull;     /* fib(92) */
    count = 93-2;                   /* not using fib(1) or fib(0) */
    scanf("%llu", &x);  /* llu needed for 64 bit input for VS */
    if (x == 0){
        printf("0\n");
        return 0;
    }
    y = x;          /* save x */
    while(x != 0){                  /* main loop */
        if(x >= a){                 /* if x >= fib(count+2) */
            x -= a;                 /*  update x and arr */
            arr[count] = 1;
        }
        count--;
        b = a - b;                  /* b = fib(count+1) */
        a = a - b;                  /* a = fib(count+2) */
    }
    count = sizeof(arr)/sizeof(arr[0]);
    while(arr[--count] == 0);
    while(count >= 0){
        printf ("%d", arr[count]);
        count--;
    }
    printf("\n");
    /* check result */
    z = 0;
    a = 1;      /* fib(1) */
    b = 0;      /* fib(0) */
    for(count = 0; count < sizeof(arr)/sizeof(arr[0]); count++){
        a = a + b;  /* a = fib(count+2) */
        b = a - b;  /* b = fib(count+1) */
        if(arr[count] != 0)
            z += a;
    }
    if(y != z)
        printf("mistmatch\n");
    return 0;
}