Fibodigits - 计算斐波那契数位
Fibodigits - count the digits of Fibonacci
我需要找到 1000 位的斐波那契数位。
例如:1有1位,10有2位,100有3位...
斐波那契数列以这种方式开始:0,1,2,3,5,8,13...
我必须插入 1000 并得到结果 4782。
我得到 4781 插入 524 见下文。我想插入 1000 并得到 4782。有什么方法可以得到我的堆栈长度吗?在 python 中我可以使用 len 函数,在 C 中它不起作用:)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int s) {
int i = 1;
int k = 1;
int list[1000] = { 0, 1 };
int fibo = 0;
int s = -1;
int divide = 0;
while (i < 1500) {
i++;
fibo = list[i - 1] + list[i - 2];
if (i == 1000) {
break;
} else {
list[i] = fibo;
//printf("%d\n", list[i]);
}
}
while (s < 524) {
s++;
divide = 0;
while (list[s] != 0) {
divide = list[s] / 10;
list[s] = divide;
k++;
if(divide == 0) {
break;
}
}
}
printf("%d\n", k);
}
这个简单的问题在C中比在Python中更难解决:与Python不同,C默认没有多精度整数运算,所以你必须自己实现,至少对于加法,最好以 10 为基数。
这是一个快速而简单的实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct bignum {
int len;
unsigned char *digits;
} bignum;
void bignum_init(bignum *a, int v) {
a->len = 1;
a->digits = malloc(1);
if (a->digits == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
a->digits[0] = (unsigned char)v;
}
void bignum_free(bignum *a) {
free(a->digits);
a->digits = NULL;
a->len = 0;
}
void bignum_print(const bignum *a) {
int i = a->len;
while (i-- > 0)
putchar('0' + a->digits[i]);
}
void bignum_add(bignum *c, const bignum *a, const bignum *b) {
int i, aux;
if (a->len < b->len) {
const bignum *tmp = a;
a = b;
b = tmp;
}
c->digits = realloc(c->digits, a->len + 1);
if (c->digits == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
for (i = 0, aux = 0; i < b->len; i++) {
aux += a->digits[i] + b->digits[i];
c->digits[i] = aux % 10;
aux /= 10;
}
for (; i < a->len; i++) {
aux += a->digits[i];
c->digits[i] = aux % 10;
aux /= 10;
}
if (aux != 0) {
c->digits[i++] = (unsigned char)aux;
}
c->len = i;
}
int main(int argc, char *argv[]) {
int i, n;
if (argc > 1) {
n = strtol(argv[1], NULL, 0);
} else {
if (scanf("%d", &n) != 1)
return 1;
}
bignum B[3];
bignum_init(&B[0], 0);
bignum_init(&B[1], 1);
bignum_init(&B[2], 1);
for (i = 3;; i++) {
bignum_add(&B[i % 3], &B[(i - 1) % 3], &B[(i - 2) % 3]);
if (B[i % 3].len >= n)
break;
}
printf("%d\n", i);
// for debugging
//printf("fib(%d) = ", i);
//bignum_print(&B[i % 3]);
//printf("\n");
bignum_free(&B[0]);
bignum_free(&B[1]);
bignum_free(&B[2]);
return 0;
}
这是一个使用近似值的快捷方式实现,即使对于非常小的数字也能很好地工作:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int n;
if (argc > 1) {
n = strtol(argv[1], NULL, 0);
} else {
if (scanf("%d", &n) != 1)
return 1;
}
double phi = (1.0 + sqrt(5.0)) / 2.0;
printf("%g\n", ceil(n / log10(phi) - 3.0));
return 0;
}
phi
是黄金比例。斐波那契数列很快收敛到黄金比例的几何数列。换句话说,fib(n)
大约是 pow(phi, n - 3)
。将此等式反转 10i 即可得到解。
我需要找到 1000 位的斐波那契数位。
例如:1有1位,10有2位,100有3位...
斐波那契数列以这种方式开始:0,1,2,3,5,8,13...
我必须插入 1000 并得到结果 4782。
我得到 4781 插入 524 见下文。我想插入 1000 并得到 4782。有什么方法可以得到我的堆栈长度吗?在 python 中我可以使用 len 函数,在 C 中它不起作用:)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int s) {
int i = 1;
int k = 1;
int list[1000] = { 0, 1 };
int fibo = 0;
int s = -1;
int divide = 0;
while (i < 1500) {
i++;
fibo = list[i - 1] + list[i - 2];
if (i == 1000) {
break;
} else {
list[i] = fibo;
//printf("%d\n", list[i]);
}
}
while (s < 524) {
s++;
divide = 0;
while (list[s] != 0) {
divide = list[s] / 10;
list[s] = divide;
k++;
if(divide == 0) {
break;
}
}
}
printf("%d\n", k);
}
这个简单的问题在C中比在Python中更难解决:与Python不同,C默认没有多精度整数运算,所以你必须自己实现,至少对于加法,最好以 10 为基数。
这是一个快速而简单的实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct bignum {
int len;
unsigned char *digits;
} bignum;
void bignum_init(bignum *a, int v) {
a->len = 1;
a->digits = malloc(1);
if (a->digits == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
a->digits[0] = (unsigned char)v;
}
void bignum_free(bignum *a) {
free(a->digits);
a->digits = NULL;
a->len = 0;
}
void bignum_print(const bignum *a) {
int i = a->len;
while (i-- > 0)
putchar('0' + a->digits[i]);
}
void bignum_add(bignum *c, const bignum *a, const bignum *b) {
int i, aux;
if (a->len < b->len) {
const bignum *tmp = a;
a = b;
b = tmp;
}
c->digits = realloc(c->digits, a->len + 1);
if (c->digits == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
for (i = 0, aux = 0; i < b->len; i++) {
aux += a->digits[i] + b->digits[i];
c->digits[i] = aux % 10;
aux /= 10;
}
for (; i < a->len; i++) {
aux += a->digits[i];
c->digits[i] = aux % 10;
aux /= 10;
}
if (aux != 0) {
c->digits[i++] = (unsigned char)aux;
}
c->len = i;
}
int main(int argc, char *argv[]) {
int i, n;
if (argc > 1) {
n = strtol(argv[1], NULL, 0);
} else {
if (scanf("%d", &n) != 1)
return 1;
}
bignum B[3];
bignum_init(&B[0], 0);
bignum_init(&B[1], 1);
bignum_init(&B[2], 1);
for (i = 3;; i++) {
bignum_add(&B[i % 3], &B[(i - 1) % 3], &B[(i - 2) % 3]);
if (B[i % 3].len >= n)
break;
}
printf("%d\n", i);
// for debugging
//printf("fib(%d) = ", i);
//bignum_print(&B[i % 3]);
//printf("\n");
bignum_free(&B[0]);
bignum_free(&B[1]);
bignum_free(&B[2]);
return 0;
}
这是一个使用近似值的快捷方式实现,即使对于非常小的数字也能很好地工作:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int n;
if (argc > 1) {
n = strtol(argv[1], NULL, 0);
} else {
if (scanf("%d", &n) != 1)
return 1;
}
double phi = (1.0 + sqrt(5.0)) / 2.0;
printf("%g\n", ceil(n / log10(phi) - 3.0));
return 0;
}
phi
是黄金比例。斐波那契数列很快收敛到黄金比例的几何数列。换句话说,fib(n)
大约是 pow(phi, n - 3)
。将此等式反转 10i 即可得到解。