[英]Fibonacci function with big number (i.e. 1000 digits) in C
EDIT: I replace: carry = (x-(x%10))%10; 编辑:我替换:进位=(x-(x%10))%10; by: carry = x/10;
通过:进位= x / 10;
And I add at the end of the while loop in addition(): if(carry) f3[i] = carry; 我在while循环的末尾添加了add():if(carry)f3 [i] =进位;
I'm working on problem 25 of Project Euler (beware spoilers), and while the fibonacci function isn't really a problem I've difficulties to implement a way to store huge number (like there a 1000 digits). 我正在研究Euler项目的问题25(当心破坏者),虽然fibonacci函数并不是真正的问题,但我很难实现一种存储大量数字的方法(例如,那里有1000位数字)。
So i've tried (as i learnt on the web) to deal with it with array, but the program is running indefinitely. 因此,我尝试(如在网络上学到的)使用数组处理它,但是该程序无限期地运行。 My problem is probably in addition() or length().
我的问题可能是addition()或length()。
Any ideas about it ? 有什么想法吗?
#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;
}
You could use GMP multiple precision library: https://gmplib.org . 您可以使用GMP多精度库: https : //gmplib.org 。 You may also want to check Fibonacci section: https://gmplib.org/manual/Fibonacci-Numbers-Algorithm.html .
您可能还需要检查Fibonacci部分: https : //gmplib.org/manual/Fibonacci-Numbers-Algorithm.html 。
UPDATE You may also want to check this post, which demonstrates how to implement fast Fibonacci from scratch: https://www.anfractuosity.com/2012/10/24/fib-calculation-with-gmp . 更新您可能还需要查看这篇文章,该文章演示了如何从头开始实现快速斐波那契: https : //www.anfractuosity.com/2012/10/24/fib-calculation-with-gmp 。
Pros of using GMP are that you will have a really fast and elaborated algorithms, written by people who know what they do. 使用GMP的优点是,您将拥有真正快速且精心设计的算法,这些算法是由知道自己在做什么的人编写的。 GMP is extremely fast (it is partially written in assembler and makes a deep use of various algorithms), mature and stable library.
GMP非常快(它是部分地用汇编语言编写的,并且充分利用了各种算法),成熟且稳定的库。 Whenever you need to work with big numbers, it's always a good idea to use GMP.
每当您需要处理大量数据时,使用GMP总是一个好主意。
Well, seems like your problem is in this line: 好吧,看来您的问题出在这一行:
carry = (x - x%10) % 10;
it should be just 应该只是
carry = x - x%10;
or 要么
carry = x / 10;
which is equivalend in this case. 在这种情况下是等效的。
UPDATE: also, in line 更新:还行
while ( (f1[i] >= 0) || (f2[i] >= 0) ) {
if the size of f1
is siz
and the size of f2
is also siz
, then you'll reach the element f1[siz]
, or even further, which is out of range . 如果
f1
的大小是siz
, f2
的大小也是siz
,那么您将到达元素f1[siz]
,甚至更远,它超出范围 。 So, you should declaring 所以,你应该声明
int f1[siz+1], f2[siz+1], f3[siz+1]
and you should setting siz+1
edges everywhere: 并且您应该在各处设置
siz+1
边线:
memset( fi, -1, (siz+1)*sizeof(int)); // where 1 <= i <= 3
PS: if you only want to calculate that fibonacci number without integrating into some program that requires fast calculation, it's better to use Python
or Java
, because these languages have built-in long numbers support and their syntax are very easy and similar to C++
. PS:如果您只想计算斐波那契数而不集成到需要快速计算的程序中,则最好使用
Python
或Java
,因为这些语言具有内置的长数字支持,并且它们的语法非常简单并且类似于C++
。 And, as ghostmansd mentioned above, it's better to use GMP library if you're going to use C/C++ anyways. 而且,正如上面的ghostmansd所述,如果您仍然要使用C / C ++,最好使用GMP库 。
There are several problems with your code. 您的代码有几个问题。
Your numbers are terminated by a digit with the sentinel value −1. 您的号码以前哨值为-1的数字结尾。 You need space for that extra digit, much like you need space for the null terminator in C strings.
您需要为多余的数字留出空间,就像您需要为C字符串中的空终止符留出空间一样。 You should dimension your arrays to
siz + 1
and initialise all values including the dummy value. 您应该将数组的尺寸设置为
siz + 1
并初始化所有值,包括虚拟值。
When you add two numbers, you never consider the last carry. 当您将两个数字相加时,您永远不会考虑最后一个进位。 That means that your numbers never get longer.
这意味着您的电话号码永远都不会更长。 Add this after the main lop in
addition
: addition
,将其添加到主折叠后:
if (carry) f3[i] = carry;
Your method to determine the carry isn't correct, either. 您确定进位的方法也不正确。 The carry are the excess digits to the left:
进位是左边的多余数字:
carry = x / 10;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.