关于大数阶乘 (相乘) 高手指点 c语言大数加法,乘法,阶乘!急求!

程序如下:
#include<stdio.h>
#include<stdlib.h>

#define D_type unsigned short int //数据类型
#define M_D_type unsigned long int //移位类型,数据类型的两倍长度
#define S_ARR 0 //源数组(参加阶乘的所有数)
#define T_ARR 1 //临时移位数组
#define R_ARR 2 //临时结果数组

typedef struct node
{
char content;
struct node * next;
}node,*Link,**Link_h;

//函数声明部分
int list_insert( Link_h head , D_type obj);
int clear_arr( D_type ** arr , D_type size , int num);
int is_one( D_type obj , int n_bit);
int move_bit( D_type ** arr , D_type size , int n_bit);
int add_bit( D_type ** arr , int size );
int move_result( D_type ** arr , D_type size);
int jiecheng(D_type ** arr,int size);
int long_data_convert( D_type ** arr , D_type size , Link_h list );
int long_data_print( Link list );

//链表插入元素(头插法)
int list_insert( Link_h head , D_type obj)
{
Link pointer;
pointer = (Link)malloc(sizeof(node));
pointer->content = (char)obj;
pointer->next = *head;
*head = pointer;
}

//清除数组内容
int clear_arr( D_type ** arr , D_type size , int num)
{
long long int i;
i = size;
while( i + 1 )
{
arr[num][i--] = 0;
}
return(0);
}

//判断乘数n_bit位是否为1
int is_one( D_type obj , int n_bit)
{
//右数第n_bit位为零(位数从0开始),返回值为零,否则非零
return( obj & ( (D_type)1 << n_bit ) );
}

//被乘数向左移n_bit位,并保存到临时移位数组
//等待与以前位与被乘数相乘结果相加
int move_bit( D_type ** arr , D_type size , int n_bit)
{
int i = 0;
D_type low = 0 , high = 0;
clear_arr( arr , size , T_ARR ); //清空临时移位数组
while( !arr[ S_ARR ][i])
{
i++;
}
for( ; i < size ; i++ ) //从第一位非零数开始左移位
{
low = high = arr[ S_ARR ][i];
low <<= n_bit;
high >>= (8 * sizeof(D_type) - n_bit);
arr[ T_ARR ][i] |= high; //交叉位处理
arr[ T_ARR ][ i + 1 ] = low; //新增位赋值
}
return(0);
}
//把移位后结果与以前结果相加
//暂时保存此次移位后结果
int add_bit( D_type ** arr , int size )
{
int i;
M_D_type temp = 0;
for( i = size ; i >= 0 ; i-- ) //从最后一位开始相加
{
temp += arr[ T_ARR ][i] + arr[ R_ARR ][i]; //对应位相加,temp前部分保存进位
arr[ R_ARR ][i] = temp; //后部分对结果数组赋值
temp >>= (8 * sizeof(D_type));
}
return(0);
}

//把结果移动到被乘数
int move_result( D_type ** arr , D_type size)
{
int i;
for( i = 0 ; i <= size ; i++ )
{
arr[ S_ARR ][i] = arr[ R_ARR ][i]; //临时结果数组copy给源数组
}
return(0);
}

//把输入数组的阶乘求出,二进制表示在原来数组的内存中
int jiecheng(D_type ** arr,int size)
{
int i,n_bit;
arr[ S_ARR ][0] = 1; //源数组零号元素赋值
for(i = 1 ; i < size ; i++)
{
arr[ S_ARR ][i] = i + 1; //源数组i号元素赋值
clear_arr( arr , i , R_ARR ); //临时结果数组清零
//处理乘数第0到n_bit位与被乘数的积
for(n_bit = 0 ; n_bit < (sizeof(D_type) * 8) ; n_bit++)
{
if(is_one(arr[ S_ARR ][i],n_bit))
{
move_bit(arr,i,n_bit);
add_bit(arr,i);
}
}
move_result(arr,i);
}
}

int long_data_convert( D_type ** arr , D_type size , Link_h head )
{
int i = 0,j;
while( !arr[ S_ARR ][i] )
{
i++;
}
M_D_type temp = 0,yushu = 0;
while( i < size )
{
yushu = 0;
for( j = i ; j < size ; j++ )
{
yushu <<= (sizeof( D_type ) * 8);
temp = arr[ S_ARR ][j] + yushu;
yushu = temp % 10;
arr[ S_ARR ][j] = temp / 10;
}
list_insert( head , yushu );
if( !arr[ S_ARR ][i])
{
i++;
}
}
}

int long_data_print( Link head )
{
Link p;
D_type bit_sum = 0;
while( head )
{
p = head;
printf("%d",head->content);
head = head->next;
free(p);
bit_sum++;
}
printf("\nthe result has %d bits!\n",bit_sum);
return(0);
}

int main(int argc , char ** argv )
{
Link head = NULL;
D_type size,*arr[3];
printf("input the number:");
scanf("%ld",&size);
printf("\n");
if((arr[ S_ARR ] = (D_type *)malloc( size * sizeof(D_type) )) == NULL)
{
printf("Source array memory allocate failure!\n");
return(-1);
}
if((arr[ T_ARR ] = (D_type *)malloc( size * sizeof(D_type) )) == NULL)
{
printf("Temp array memory allocate failure!\n");
return(-1);
}
if((arr[ R_ARR ] = (D_type *)malloc( size * sizeof(D_type) )) == NULL)
{
printf("Result array memory allocate failure!\n");
return(-1);
}
jiecheng( arr , size );
long_data_convert( arr , size , &head);
long_data_print( head );
return(0);
}
大家多指点哈,如果有很多的建议,又很想帮帮小菜鸟的,可以给我发邮件:[email protected]
谢谢大家了!

//看看这个程序吧,我以前写的,主要方向就是用数组来模拟,一开始用数组每个元素来表示一位,但是可以优化成每个元素表示4位,这样更快更省空间,现在这个版本是double数组,每个元素表示11位,50000阶乘都没有问题,算大的只是时间长一点。每次乘的时候不是乘数组的每一位,而是定位一个实际有效的区间,这样更优化
#include<stdio.h>
#include<math.h>
#include<time.h>
#include<conio.h>
#define LEN 44000
#define DEP 11
double ans[LEN]={1};
void main()
{
int i,j,n,r,l;
long c1,c2;
double m,h=0,z=0,k=pow(10,DEP);
printf("\t阶乘运算 v1.1 by CityHunter\t2006-09\n");
printf("\n请输入n: ");
scanf("%d",&n);
printf("完成\t\t");
c1=clock();
for(i=2;i<=n;i++)
{
for(l=i;l>0&&l%5==0;l/=5)
z+=1.0/DEP;
h+=log10(i)/DEP;
if(z>1)
r=z-1;
else
r=0;
for(j=r;j<h;j++)
ans[j]*=i;
for(j=r;j<h;j++)
if(ans[j]>=k)
{
ans[j+1]+=(int)(ans[j]/k);
ans[j]=(ans[j])-(int)(ans[j]/k)*k;
}
if(i%500==0)
{
printf("%3d%%",i*100/n);
printf("\b\b\b\b");
}
}
printf("100%%\n");
c2=clock();
for(j=h+1;ans[j]==0;j--);
printf("\n%.0lf",ans[j--]);
for(;j>-1;j--)
{
for(m=k/10;ans[j]<m&&m>1;m/=10)
printf("0");
printf("%.0lf",ans[j]);
}
printf("\n\n%dms\n",c2-c1);
getch();
}

这个问题我也考虑过。二进制的运算没什么问题,难点在于输入、输出。把一个十进制的大数转换为二进制的很麻烦(因为长度太大,用短除法的时候还要模拟竖式除法);把二进制转换为十进制的话更麻烦,我至今没想到好的方法。

我劝你用数组,10000进制,模拟竖式。

基本不可行
怎么输出结果
直接用数组,数组的每个元素表示一位

扩展阅读:阶乘计算公式 ... 幻和 中间数 公式 ... 乘数和被乘数 积 口诀 ... 平方万能速算方法 ... 数学题 团体十人以上 ... 被除数 除数 商 的关系 ... 语大全 万人计划 ... 大数阶乘c语言程序 ... 印度乘法口诀一览表 ...

本站交流只代表网友个人观点,与本站立场无关
欢迎反馈与建议,请联系电邮
2024© 车视网