计算 斐波那契数列第 n 项的十进制位数 w 与 n 的数学关系

参阅上一篇:bellard.org‌ : QuickJS 如何使用 qjs 执行 js 脚本

(Fibonacci sequence)斐波那契数列第 n 项的十进制位数 w 与 n 的数学关系可用以下公式近似表示:

 推导过程:

示例验证: 

当 n=100 , 计算 w := 100*0.2089878 +1 = 21.89878 := 22
:= 读作 约等于。BigInt 符号(+, -) 需要占1位。

校验,运行 python fibonacci.py 100
F(100): 354224848179261915075

结论:

斐波那契数的位数 w 与 n 呈近似线性关系,比例系数为 log⁡10(ϕ),公式误差随 n 增大可忽略。


 从 bellard.org 下载 tcc-0.9.27-win64-bin.zip 到 D:\tcc\ , 然后解压。
cd D:\tcc\tcc

为了计算 斐波那契数列Fibonacci sequence),编写 fib_bigint.c  如下

#include <stdio.h>
#include <stdlib.h>	// atoi()
#include <string.h>
#define MAXLEN 13600

// 初始化 bigint a(0), b(1), c(0);
    char a[MAXLEN] = {'0'};
    char b[MAXLEN] = {'1'};
    char c[MAXLEN] = {'0'};

// 将大数存储为字符串形式,并通过反转操作使‌低位对齐‌以便计算
void reverseString(char *str) {
    int len = strlen(str);
    for (int i = 0; i < len / 2; i++) {
        char temp = str[i];
        str[i] = str[len - i - 1];
        str[len - i - 1] = temp;
    }
}

// 逐位加法与进位处理
void addBigInt(char *num1, char *num2)
{
    int len1 = strlen(num1), len2 = strlen(num2);
    int maxLen = (len1 > len2) ? len1 : len2;
    
    int carry = 0;
    for (int i = 0; i < maxLen; i++) {
        int digit1 = (i < len1) ? (num1[i] - '0') : 0;
        int digit2 = (i < len2) ? (num2[i] - '0') : 0;
        int sum = digit1 + digit2 + carry;

        c[i] = (sum % 10) + '0';
        carry = sum / 10;
    }

    if (carry > 0) c[maxLen++] = carry + '0';
    c[maxLen] = '\0';
    return;
}
    
// Fibonacci Series compute
char* calc_fib(int n)
{   
    if (n <= 0) return "0";
    if (n == 1) return "1";

    for(int i = 2; i <= n; i++) {
        addBigInt(a, b); // 和值存入 c
        strcpy(a, b);
        strcpy(b, c);
    }
    return b;
}

int main(int argc, char **argv) 
{
	int n;
	if (argc < 2) {
		printf("usage: fib_bigint n \n"
			   "Compute nth Fibonacci number\n");
		return 1;
	}
		
	n = atoi(argv[1]);
    if (n <=0){ printf("input error"); return 1;}
    // MAXLEN: 13600/0.2089878 := 65075.57 -2 := 65074 
    if (n >= 65074){ printf("input too big: n < 65074",n); return 2;}
    
    char* res = calc_fib(n);
    if(strlen(res) >1) printf("%d: ", strlen(res));  
    reverseString(res);
	printf("fib(%d) = %s\n", n, res); 
	return 0;
}

关键注意事项

  1. 对齐问题‌:反转字符串确保低位对齐,简化计算逻辑。
  2. 进位处理‌:每一步相加需更新进位,循环结束后检查剩余进位。
  3. 动态内存‌:结果数组需动态分配以避免栈溢出,并及时释放。
  4. 前导零处理‌:反转结果前需跳过可能的无效前导零(如输入“0098”)。

编译 tcc fib_bigint.c -o fib_bigint.exe
运行 fib_bigint 1000
209: fib(1000) = 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

运行 fib_bigint 66000
input too big: n < 65074

也可以即时运行 tcc -run fib_bigint.c  10000
2090: fib(10000) = ......

cd D:\tcc\quickjs-cosmo-2025-04-26
校验:qjs fib_bigint.js 1000
43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值