开发斐波那契计算器时,如何获取超出_BitInt(65535)上限的更大整数?
解决_BitInt位数限制,实现大整数斐波那契计算
方法1:手动实现动态数组模拟大整数
用数组存储大整数的每一位(十进制或二进制),自己实现加法逻辑,完全不受位数限制,只要内存足够就能支持任意大的数。
示例代码(十进制存储):
#include <stdio.h> #include <stdlib.h> #include <string.h> // 大整数结构体:数组存每一位十进制数字,len为有效位数 typedef struct { int *digits; int len; } BigInt; // 用无符号长整数初始化大整数 BigInt bigint_init(unsigned long long num) { BigInt bi; if (num == 0) { bi.len = 1; bi.digits = malloc(sizeof(int)); bi.digits[0] = 0; return bi; } int temp = num, count = 0; while (temp > 0) { temp /= 10; count++; } bi.len = count; bi.digits = malloc(sizeof(int) * count); temp = num; for (int i = count - 1; i >= 0; i--) { bi.digits[i] = temp % 10; temp /= 10; } return bi; } // 大整数加法 BigInt bigint_add(BigInt a, BigInt b) { BigInt res; int max_len = a.len > b.len ? a.len : b.len; // 预留一位存进位 res.digits = malloc(sizeof(int) * (max_len + 1)); int carry = 0, i; // 从低位到高位相加 for (i = 0; i < max_len; i++) { int digit_a = i < a.len ? a.digits[a.len - 1 - i] : 0; int digit_b = i < b.len ? b.digits[b.len - 1 - i] : 0; int sum = digit_a + digit_b + carry; res.digits[max_len - i] = sum % 10; carry = sum / 10; } // 处理剩余进位 if (carry > 0) { res.digits[0] = carry; res.len = max_len + 1; } else { res.len = max_len; memmove(res.digits, res.digits + 1, sizeof(int) * max_len); } return res; } // 打印大整数 void bigint_print(BigInt bi) { for (int i = 0; i < bi.len; i++) { printf("%d", bi.digits[i]); } printf("\n"); } // 释放大整数内存 void bigint_free(BigInt bi) { free(bi.digits); } int main(void) { int n = 99999; BigInt a = bigint_init(1); BigInt b = bigint_init(1); if (n >= 1) { printf("fib: "); bigint_print(a); } for (int i = 2; i <= n; i++) { BigInt c = bigint_add(a, b); bigint_free(a); a = b; bigint_free(b); b = c; printf("fib: "); bigint_print(a); } bigint_free(a); bigint_free(b); return 0; }
方法2:使用第三方大整数库
用成熟的开源库比如GMP(GNU多精度算术库),它支持任意精度的整数运算,比手动实现更高效可靠。
示例代码(GMP版):
#include <stdio.h> #include <gmp.h> int main(void) { int n = 99999; mpz_t a, b, c; // 初始化并设置初始值 mpz_init_set_ui(a, 1); mpz_init_set_ui(b, 1); if (n >= 1) { printf("fib: "); mpz_out_str(stdout, 10, a); printf("\n"); } for (int i = 2; i <= n; i++) { mpz_add(c, a, b); mpz_swap(a, b); mpz_swap(b, c); printf("fib: "); mpz_out_str(stdout, 10, a); printf("\n"); } // 释放资源 mpz_clear(a); mpz_clear(b); mpz_clear(c); return 0; }
编译时需要链接GMP库:gcc fib.c -o fib -lgmp
方法3:用字符串模拟大整数加法
如果不想用结构体或第三方库,直接用字符串存储数字,实现字符串形式的加法,代码更简洁但效率略低,适合小范围大整数计算。
示例代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> // 字符串加法,返回结果字符串(需手动释放) char* str_add(const char* a, const char* b) { int len_a = strlen(a); int len_b = strlen(b); int max_len = len_a > len_b ? len_a : len_b; // 预留进位和结束符空间 char* res = malloc(sizeof(char) * (max_len + 2)); int carry = 0, i = len_a - 1, j = len_b - 1, k = 0; while (i >= 0 || j >= 0 || carry > 0) { int digit_a = i >= 0 ? a[i--] - '0' : 0; int digit_b = j >= 0 ? b[j--] - '0' : 0; int sum = digit_a + digit_b + carry; res[k++] = (sum % 10) + '0'; carry = sum / 10; } res[k] = '\0'; // 反转字符串得到正确顺序 for (int m = 0; m < k / 2; m++) { char temp = res[m]; res[m] = res[k - 1 - m]; res[k - 1 - m] = temp; } return res; } int main(void) { int n = 99999; char* a = strdup("1"); char* b = strdup("1"); if (n >= 1) { printf("fib: %s\n", a); } for (int i = 2; i <= n; i++) { char* c = str_add(a, b); free(a); a = b; free(b); b = c; printf("fib: %s\n", a); } free(a); free(b); return 0; }
另外注意你原有代码里的printf("%u", a);是错误的,u65535类型不能用%u格式化,即使位数没超限也应该用GCC支持的%Bd格式符,但这解决不了位数不足的问题,所以还是用上面的大整数方案更合适。
内容的提问来源于stack exchange,提问作者Ibolya Vojtek
相关产品推荐
相关产品推荐

