我正在尝试计算100!
我正在寻找使用C来实现这一目标的最简单方法。我已经阅读过但未找到具体答案。
如果你必须知道,我在Mac OS X中用Xcode编程。
谢谢!
答案 0 :(得分:23)
如果您正在寻找一个简单的库,libtommath(来自libtomcrypt)可能就是您想要的。
如果您正在寻找自己编写一个简单的实现(或者作为学习练习,或者因为您只需要一个非常有限的bigint功能子集,并且不希望依赖于大型库,命名空间污染,等),那么我可能会为您的问题建议以下内容:
由于您可以根据n
绑定结果的大小,只需预先分配一个所需大小的uint32_t
数组来保存结果。我猜你要打印结果,所以使用10的幂(即基数1000000000)而不是2的幂是有意义的。也就是说,允许数组的每个元素保存0到999999999之间的值。
要将此数字乘以(正常,非大)整数n
,请执行以下操作:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp % 1000000000;
carry = tmp / 1000000000;
}
if (carry) big[len++] = carry;
如果您知道n
永远不会超过100(或其他一些小数字)并且想要避免进入64位范围(或者如果您使用的是64位平台并希望对你的bigint数组使用uint64_t
,然后使基数为10的较小幂,这样乘法结果将始终适合该类型。
现在,打印结果就像:
printf("%lu", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.9lu", (long)big[i-1]);
putchar('\n');
如果你想使用2的幂作为基数,而不是10的幂,则乘法变得更快:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp;
carry = tmp >> 32;
}
if (carry) big[len++] = carry;
但是,以十进制打印结果不会那么令人愉快... :-)当然如果你想要十六进制的结果,那么很容易:
printf("%lx", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.8lx", (long)big[i-1]);
putchar('\n');
希望这有帮助!我会留下实施其他东西(比如加法,乘以2个bigint等)作为练习。回想一下你是如何学习如何在小学阶段进行基础10加法,乘法,除法等,并教导计算机如何做到这一点(但在基数-10 ^ 9或基数-2 ^ 32代替)你应该没问题。
答案 1 :(得分:6)
如果您愿意使用库实现,那么标准实现似乎是GMP
mpz_t out;
mpz_init(out);
mpz_fac_ui(out,100);
mpz_out_str(stdout,10,out);
应该算100!从查看文档。
答案 2 :(得分:2)
您也可以使用OpenSSL bn;它已经安装在Mac OS X中。
答案 3 :(得分:1)
您要求使用最简单的方法来执行此操作。那么,你走了:
#include <gmp.h>
#include <stdio.h>
int main(int argc, char** argv) {
mpz_t mynum;
mpz_init(mynum);
mpz_add_ui(mynum, 100);
int i;
for (i = 99; i > 1; i--) {
mpz_mul_si(mynum, mynum, (long)i);
}
mpz_out_str(stdout, 10, mynum);
return 0;
}
我测试了这段代码并给出了正确答案。