用数组实现大数的阶乘

本文介绍了一种使用数组模拟寄存器乘法计算大数阶乘的方法,通过自定义函数facth和factd实现了10000!的快速计算,并提供了C语言实现代码。

用int来表示整数的阶乘到12!就是极限了,再大就要超出整数的范围了

那么更大的数的阶乘怎么办, long long int是64位,但是也只能容纳20!的阶乘,更大的数必须另想办法

直接上代码, 10000!  0.1s左右可得(i7的cpu哈)。

这个时间也不包含输出部分, 具体的时间和硬件有关系

基本原理就是用数组模拟寄存器乘法计算的原理


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define MAX 50000
// 10000!  用到数组不到4000位,如果要计算更大的, 需要把MAX放大
// facth和factd两个函数返回的数值就是表示数组实际使用的大小
// 如果想放开这个限制,可以用vector动态数组模板来替代facts这个静态数组
int facts[MAX];
int facth(int n) { // 16进制的乘法 
	if ( 0==n || 1==n ) {
		facts[0] = 1;
		return 1;
	}
	memset(facts, 0, MAX*sizeof(int));
	facts[0] = 1;  int len = 1;  
	for (int i=2; i<n; i++) {
		int  extend = 0;
		long long int d;
		for ( int j=0; j<len; j++) {
			long long int a = facts[j];
			d = a * i + extend;
			facts[j] = d & 0xFFFFFFFF;
			extend = d >> 32;
		}
		if ( extend>0) {
			facts[len] = extend;
			len ++; extend = 0;
		}
	//	printf("%2d: %8x -  %8x - %8x - %8x \n", i, facts[3], facts[2], facts[1], facts[0]);
	}
	return len;  
}
int factd(int n) { // 16进制的乘法 
	if ( 0==n || 1==n ) {
		facts[0] = 1;
		return 1;
	}
	memset(facts, 0, MAX*sizeof(int));
	facts[0] = 1;  int len = 1;  
	for (int i=2; i<=n; i++) {
		int  extend = 0;
		long long int d;
		for ( int j=0; j<len; j++) {
			long long int a = facts[j];
			d = a * i + extend;
			if ( d > 1000000000) {		
				facts[j] = d % 1000000000;
				extend   = d / 1000000000;
			} else
				facts[j] = d, extend=0; 
		}
		if ( extend>0) {
			facts[len] = extend;
			len ++;
			extend = 0;
		}
		//printf("%2d: %9d -  %9d - %9d - %9d \n", i, facts[3], facts[2], facts[1], facts[0]);
	}
	return len;  
}

void printd(int len) {
	printf("len:%d\n", len);
	if (len>1) {
		printf("%d ", facts[len-1]);
		for ( int i=len-2; i>=0; i--) 
			printf("%09d ", facts[i]);
	} else
		printf("%d", facts[0]);
}

void printh(int len) {
	printf("len:%d\n", len);
	if (len>1) {
		printf("%X ", facts[len-1]);
		for ( int i=len-2; i>=0; i--) 
			printf("%08X ", facts[i]);
	} else
		printf("%X", facts[0]);
}
#include <time.h>
int main() {
	clock_t start,end;
	int len = 0;
	start = clock();
	len = facth(10000); // 十六进制的表达
	// len = factd(10000); // 十进制的表达 
	end = clock();
	printh(len); // 输出16进制,和facth配合使用 
	// printd(len); // 输出十进制,和factd配合使用 
	double endtime=(end-start)*1.0/CLOCKS_PER_SEC;
	printf("\n\ntime:%lf(s)\n", endtime);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值