Fibonacci函数在C中具有大数(即1000位)

时间:2015-09-07 13:38:45

标签: c bignum

编辑: 我替换:     carry =(x-(x%10))%10; 通过:     carry = x / 10;

我在while循环的末尾添加了():     if(carry)f3 [i] = carry;

感谢FalconUSA& M_Oehm! :)

我正在研究Project Euler的问题25(小心剧透),虽然斐波纳契函数不是真正的问题,但我很难实现存储大量数字的方法(比如1000位数)。 / p>

所以我尝试过(我在网上学到的)用数组处理它,但程序无限期地运行。 我的问题可能是加法()或长度()。

关于它的任何想法?

#include <stdio.h>
#include <string.h>

int length(int *nbr) // number of digits of my number
{
    int len = 0, c = 0;

    while(nbr[c] >= 0) {
        len++;
        c++;
    }
    return len;
}

int addition(int *f1, int *f2, int *f3, int siz) // add f1+f2 and store it in f3
{
    int carry =0, i =0;
    int x;

    memset ( f3, -1, siz*sizeof(int));

    while ( (f1[i] >= 0) || (f2[i] >= 0) ) {
        if(f1[i]<0) {
            x = f2[i] + carry;
        }
        else if(f2[i]<0) {
            x = f1[i] + carry;
        }
        else {
            x = f1[i] + f2[i] + carry;
        }
        f3[i] = x%10;
        carry = (x-(x%10))%10;
        i++;
    }

    return 0;
}

int copy_arr(int *dest, int *or, int siz) //copy array "or" into "dest"
{
    int c = 0;
    memset( dest, -1, siz*sizeof(int));

    while( c < siz ) {
        dest[c] = or[c];
        c++;
    }

    return 0;
}

int fibo(int siz) //fibonacci function
{
    int f1[siz],f2[siz],f3[siz];
    memset( f1, -1, siz*sizeof(int));
    memset( f2, -1, siz*sizeof(int));
    memset( f3, -1, siz*sizeof(int));

    int n = 2;

    f1[0] = f2[0] = 1;


    while (length(f1) <= siz) {
        n++;
        addition( f1, f2, f3, siz);
        copy_arr( f2, f1, siz);
        copy_arr( f1, f3, siz);
    }

    printf("%d\n", n);

    return 0;
}


int main() // siz's value is the number of digits I desire for my fibonacci number
{
    int siz=1000;

    fibo(siz);

    return 0;
}

3 个答案:

答案 0 :(得分:3)

您可以使用GMP多精度库:https://gmplib.org。您可能还想查看Fibonacci部分:https://gmplib.org/manual/Fibonacci-Numbers-Algorithm.html

更新您可能还想查看此帖子,该帖子演示了如何从头开始实施快速斐波纳契:https://www.anfractuosity.com/2012/10/24/fib-calculation-with-gmp

使用GMP的优点在于,您将拥有一个非常快速和详细的算法,由知道他们所做的人写的。 GMP非常快(它部分用汇编语言编写并深入使用各种算法),成熟稳定的库。每当您需要使用大数字时,使用GMP始终是个好主意。

答案 1 :(得分:1)

好吧,好像你的问题就在这一行:

carry = (x - x%10) % 10;

应该只是

carry = x - x%10;

carry = x / 10;

在这种情况下是等效的。

更新:也在行

 while ( (f1[i] >= 0) || (f2[i] >= 0) ) {

如果f1的大小为sizf2的大小也为siz,那么您将到达元素f1[siz],甚至更远,超出范围。所以,你应该声明

int f1[siz+1], f2[siz+1], f3[siz+1]

你应该在任何地方设置siz+1边缘:

memset( fi, -1, (siz+1)*sizeof(int)); // where 1 <= i <= 3

PS:如果您只想计算斐波纳契数而不需要集成到需要快速计算的某个程序中,那么最好使用PythonJava ,因为这些语言具有内置的长数字支持,并且它们的语法非常简单并且类似于C++。而且,正如上面提到的ghostmansd,如果您打算使用C / C ++,最好使用GMP library

答案 2 :(得分:1)

您的代码存在一些问题。

您的号码以哨兵值为-1的数字终止。你需要空间来容纳那个额外的数字,就像你需要C字符串中空终止符的空间一样。您应该将数组标注为siz + 1并初始化所有值,包括虚拟值。

当你添加两个数字时,你永远不会考虑最后一个数字。这意味着您的号码永远不会变长。在addition中的主要翻译之后添加:

if (carry) f3[i] = carry;

您确定携带的方法也不正确。进位是左边的多余数字:

carry = x / 10;