【问题标题】:Fibonacci function with big number (i.e. 1000 digits) in CC中具有大数字(即1000位)的斐波那契函数
【发布时间】:2015-09-07 13:38:45
【问题描述】:

编辑: 我替换: 进位 = (x-(x%10))%10; 经过: 进位 = x/10;

我在while循环的末尾添加了addition(): 如果(进位) f3[i] = 进位;

感谢 FalconUSA 和 M_Oehm ! :)

我正在处理 Project Euler 的第 25 题(小心剧透),虽然斐波那契函数并不是真正的问题,但我很难实现一种存储大量数字的方法(比如 1000 位数字)。

所以我已经尝试(正如我在网上了解到的)用数组来处理它,但是程序无限期地运行。 我的问题可能是 in addition() 或 length()。

有什么想法吗?

#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;
}

【问题讨论】:

  • 要终止此条件while ( (f1[i] &gt;= 0) || (f2[i] &gt;= 0) ) {两个部分必须同时为
  • F6 = 8;和 F7 = 13。所以我想是的,可以有不同的位数。
  • 提示:您无需编写程序即可找到答案。
  • 请从您的标题和问题中删除“已解决”。您可以自行发布答案,甚至接受它。对于有类似问题的其他人来说,这是正确的指示。

标签: c bignum


【解决方案1】:

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

更新您可能还想查看这篇文章,它演示了如何从头开始实现快速斐波那契:https://www.anfractuosity.com/2012/10/24/fib-calculation-with-gmp

使用 GMP 的优点在于,您将拥有由知道自己做什么的人编写的非常快速且精细的算法。 GMP 速度极快(部分用汇编程序编写,并深度利用了各种算法),成熟稳定的库。每当您需要处理大数字时,使用 GMP 总是一个好主意。

【讨论】:

  • 谢谢你的推荐,我会看看的,但是我第一次接触 BigNum,我想自己处理一下,了解它是如何工作的。
【解决方案2】:

嗯,看来你的问题出在这一行:

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

应该只是

carry = x - x%10;

carry = x / 10;

在这种情况下是等价的。

更新:同样,在行

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

如果f1 的大小是siz 并且f2 的大小也是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

【讨论】:

  • 您对进位部分的看法是正确的,但是“siz+1”并不能使它起作用。我的程序只需“大小”即可完美运行。谢谢:)
  • 我认为它恰好起作用。您计算直到长度大于siz。发生这种情况时,您会检查超出大小的数字,这是未定义的行为。发生的情况是您只计算了一个不准确的长度,但大于满足您的条件的siz。您可以在每次迭代中打印长度以进行检查。 (当然,一个 1000 + 1 位的数字只能包含长度为 1000 的数字,并且条件 length(f1) &lt;= 1000 将始终为真,因此您需要修复的不仅仅是维度。)
【解决方案3】:

您的代码有几个问题。

您的号码以标记值为 -1 的数字结尾。您需要为那个额外的数字留出空间,就像您需要为 C 字符串中的空终止符留出空间一样。您应该将数组的维度设置为 siz + 1 并初始化所有值,包括虚拟值。

当您将两个数字相加时,您永远不会考虑最后一个进位。这意味着您的数字永远不会变长。在addition的主循环之后添加这个:

if (carry) f3[i] = carry;

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

carry = x / 10;

【讨论】:

  • 您对携带部分是正确的,但“siz+1”不是。它适用于我原来的“大小”。谢谢:)
猜你喜欢
  • 1970-01-01
  • 2021-02-14
  • 2014-05-03
  • 2018-05-30
  • 1970-01-01
  • 2020-10-18
  • 2011-05-19
  • 2016-08-09
  • 2019-12-19
相关资源
最近更新 更多