大数是算法语言中的数据类型无法表示的数,其位数超过最大数据类型所能表示的范围,所以,在处理大数问题时首先要考虑的是怎样存储大数,然后是在这种存储方式下其处理的实现方法。
一般情况下大数的存储是采用字符数组来存储,即将大数当作一个字符串来存储,而对其处理是按其处理规则在数组中模拟实现。
此次实验要求利用数组实现两个百位大数(共有100位数字)的加、减、乘法的运算。
实现下列三个函数的功能(以下函数应在fun.h中声明,在fun.c中实现)
函数原型:
/*实现两个大数的相加*/
char* add(char* data, char* addend, char* result);
/*实现两个大数的相减*/
char* minus(char* data, char* sub, char* result);
/*实现两个大数的相乘*/
char* multiply(char* data, char* mult, char* result);
在给出的程序框架中完成实验题目。
mylib.c包括此次实验的程序框架。
(在给出的程序框架中补充设计并完成实验。)
注:检验计算结果是否正确可利用提供的 test.exe 文件。
在mylib.exe和test.exe文件中输入相同的种子则会产生相同的随机大数。可以用test.exe产生的结果和mylib.exe对照结果检验对错。
请注意其中test.exe文件的输出格式和框架规定的输出格式有所不同。
提示:
字符型与整型转换
1.可以模拟笔算加减乘的过程,用数组储存大数;
2.可以用atoi和itoa函数;
3.对于一位整数的整型转换为字符型:
例:
char c;
int i = 9;
c = i+’0’;
printf(“%c”, c);
/* 姓名:**** 班级:软件三班 学号:**** 功能:百位大数 时间:2012.12.2 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "fun.h" #define N 100 /* 产生随机的大数 */ void create(char* num, unsigned seed); /*seed 为随机种子*/ char result[2 * N] = {'\0'}; int main(void) { char num[N];//多出符号位 char n[N]; //设定随机种子 unsigned int seed; printf("Please input a rand seed:"); scanf("%u", &seed); printf("\nThe seed is %u\n", seed); //产生随机大数 create(num, seed); create(n, seed+1); printf("***********************************************\n"); printf("num: %s\n n : %s\n", num, n); //调用加法 add(num, n, result); printf("num + n = %s\n", result); //调用减法 minus(num, n, result); printf("num - n = %s\n", result); //调用乘法 multiply(num, n, result); printf("num * n = %s\n", result); system("pause"); return 0; } void create(char num[], unsigned seed) { int i = 0, x = 0; int times, flag = 1; srand(seed); times = rand() % (N - 2) + 1;//避免溢出 if(rand() % 2)//随机生成负数 { num[i] = '-'; i++; if(times == 1) times++; } while(flag)//避免高位为零 { x = rand() % 10; if(x != 0) { flag = 0; } } num[i] = x + '0'; i++; for(; i < times; i++) { x = rand() % 10; num[i] = x + '0'; } num[times] = '\0'; }
#ifndef FUN_H_INCLUDED #define FUN_H_INCLUDED //此方法实现加法运算 char* add(char* data, char* addend, char* result); //此方法实现减法运算 char* minus(char* data, char* sub, char* result); //此方法实现乘法运算 char* multiply(char* data, char* mult, char* result); #endif // FUN_H_INCLUDED
#include<stdio.h> #include<stdlib.h> #include"fun.h" #include<string.h> #define N 100 //在此添加加法的实现 char* add(char* data, char* addend, char* result) { int i=0,a1,a2; char pdata[2*N]={'\0'}; char padden[2*N]={'\0'};//定义两个char类型的字符数组,并初始化每一位都置为'\0' a1=strlen(data); a2=strlen(addend);//统计两个数组中字符串长度 strcpy(pdata,data);//将字符串data复制到字符数组pdata[N]中 strcpy(padden,addend);//将字符串addend复制到字符数组padden[N]中 for(i=0;result!='\0'&&i<2*N;i++)//将字符数组result[2*N]初始化每一位都置为'\0' { result[i]='\0'; } if(pdata[0]!='-'&&padden[0]!='-')//当两个数均为正整数时 { if(a1 >= a2)//第一个数的长度大于第二个数时 { for(;a2>0;a2--,a1--)//两个正数对应位相加 { result[a1-1]=pdata[a1-1]+padden[a2-1]-'0';//将相加得到的字符结果转化为数字字符 if(result[a1-1]>'9'&&(a1-1)>0)//考虑进位的情况 { result[a1-1] -= 10; pdata[a1-2]++; } } for(;a1>=1;a1--)//第一个数比第二个数多余的位数和'0'相加得到的结果 { result[a1-1]=result[a1-1]+pdata[a1-1]; if(result[a1-1]>'9'&&(a1-1)>0) { result[a1-1]-=10;//考虑到进位的情况 pdata[a1-2]++; } } if(result[0]>'9')//当result[]中第一位>'9',要进行进位操作 { a1=strlen(data); for(;a1>0;a1--) { result[a1]=result[a1-1]; } result[1]-=10; result[0]='1';//首位进位加'1' } } else if(a1<a2)//第一个数的长度小于第二个数时,可以将加数与被加数调换再调用函数add() { add(addend,data,result); } } else if(pdata[0]=='-'&&padden[0]=='-') //当为两个数都为负数时 { result[0]='-';//result[]数组中第一位应为'-' add(&data[1],&addend[1],&result[1]); } else if(pdata[0]!='-'&&padden[0]=='-')//当第一个为正,第二个为负时,可以看做两个数相减,调用下面的minus() { minus(pdata,&padden[1],result); } else //当第一个为负,第二个为正时 { add(addend,data,result); } return result; }//在此添加减法的实现 char* minus(char* data, char* sub, char* result) { int i,b1,b2,p,dif; char pdata[N]={'\0'}, psub[N]={'\0'}; strcpy(pdata,data);//将字符串data复制到字符数组pdata[N]中 strcpy(psub,sub);//将字符串sub复制到字符数组psub[N]中 for(i=0;result[i]!='\0'&&i<N;i++)//将字符数组result[2*N]初始化每一位都置为'\0' { result[i]='\0'; } b1=strlen(pdata); b2=strlen(psub); if(pdata[0]!='-'&&psub[0]!='-')//两个数都为正数 { if(b1>b2)//第一个数位数大于第二个数时 { for(;b2-1>=0;b1--,b2--)//两个正数对应位相减 { result[b1-1]=pdata[b1-1]-psub[b2-1]+'0';//将相减得到的字符结果转化为数字字符 if(result[b1-1]<'0')//考虑相减小于0的情况,要移位处理 { result[b1-1]+=10; pdata[b1-2]--; } } p=b1; while (pdata[p-1]<'0'&&p>1)//当两个对应数相减小于'0'时,要位处理 { pdata[p-1]+=10; pdata[p-2]--; p--; } if(b1>1)//第一个数比第二个数多余的位数和'0'相减得到的结果全部赋给result[] { for(;b1>0;b1--) { result[b1-1]=pdata[b1-1]; } } while (result[0]=='0')//当移位相减后首位为'0'时 { b1=strlen(pdata); for(i=0;i<=b1;i++) { result[i]=result[i+1];//要将result[]中的数都向前移一位 } } } else if(b1 < b2)//第一个数位数大于第二个数时 { result[0]='-';//result[]数组中第一位应为'-' minus(psub,pdata,&result[1]);//将减数与被减数置换,再调用minus() } else//第一个数位数等于第二个数时 { if(pdata[0]!=psub[0])//考虑两个数组第一个数是否相等 { for(i=0;pdata[i]!=psub[i];i++) { ; } dif=i;//如果不相等下标digit设为i } else { dif=0;//如果相等下标digit设为0 } if(pdata[dif]>psub[dif])//当第一个数组中元素对应数值大于相同位的第二个数组中的元素 { for(i=( b1-dif ) ; i > 0 ; i --,b1--,dif--)//对应位上的数值相减 { result[b1-dif-1] =pdata[ b1-1 ] +'0'- psub[b2-1];//将相减得到的字符结果转化为数字字符 if(result[b1-dif-1] < '0') { pdata[ b1-2 ]--; result[b1-dif-1] += 10; } } while (result[0]=='0')//当两个数组第一位数值相同,减去得到的结果为0 { for(i = 0 ;i < b1-dif ; i++)//要将result[]数组中所有数向前移一位 { result[i]=result[i+1]; } } } else if(pdata[dif] < psub[dif])//当第一个数组中元素对应数值小于相同位的第二个数组中的元素 { result[0]='-';//两个数组第一位元素相减对应数值小于0,想减结果第一位为'-' for(i = b1;i > 0 ; i--) { pdata[i] = pdata[i-1];//要pdata[]数组中所有数向后移一位 } pdata[0] = '-';//相当于一个一个正数和一个负数做加法 add(psub,&pdata[1],&result[1]);//调用加法函数add() } else//当第一个数组中元素对应数值等于相同位的第二个数组中的元素 { result[0]='0'; result[1]='\0';//最终result[]输出结果为0 } } } else if(pdata[0]=='-'&&psub[0]!='-')//当第一个为负,第二个为正时,可以看做一个负数和一个正数做加法,调用加法函数add() { result[0]='-'; add(&pdata[1],psub,&result[1]); } else if(pdata[0]!='-'&&psub[0]=='-')//当第一个为正,第二个为负时,可以看做一个正数和一个负数做加法,调用加法函数add() { add(pdata,&psub[1],result); } else { minus(&sub[1],&data[1],result);//当两个数都为负时,调用减法函数 minus() } return result; } //在此添加乘法的实现 char *multiply(char* data, char* mult, char* result) { int digit,i,k,c1,c2,c3,num; char pdata[N]={'\0'}; char pmult[N]={'\0'};//定义两个char类型的字符数组,并初始化每一位都置为'\0' char array[2*N]={'\0'};//定义一个数组array[],用来存放第二个数每位相乘第一个数得到的结果 strcpy(pdata,data);//将字符串data复制到字符数组pdata[N]中 strcpy(pmult,mult);//将字符串mult复制到字符数组pmult[N]中 c1=strlen(data); c2=strlen(mult);//统计两个数组中字符串长度 for(i=0;result[i]!='\0'&&i<2*N;i++)//将字符数组result[2*N]初始化每一位都置为'\0' { result[i]='\0'; } if(pdata[0]!='-'&&pmult[0]!='-')//当相乘的两个数均为正整数时 { for(i=c1-1;i>=0;i--) { digit=c1-i-1;//统计array[]中需储存元素位数 num=pdata[i]-'0'; if(num>0)//当num>0时,将array[]先全部初始化每一位都置为'\0' { for(k=0;array[k]!='\0'&&k<2*N;k++) { array[k]='\0'; } for(;num>0;num--)//mult[]数组中每一位对应数值数,相应array[]中元素要乘以相同倍数,可以通过连续加法来实现 { add(array,pmult,array); } c3=strlen(array);//重新统计新得到的数组array[]中字符串长度 for(;digit>0;digit--) { array[c3+digit-1]='0'; } add(array,result,result);//需将array[]中的元素错位累加即可得到最终相乘的结果 } } } else if(pdata[0]=='-'&&pmult[0]!='-')//当第一个为负,第二个为正时,相乘结果第一位必为'-',再调用函数multiply[] { result[0]='-'; multiply(&pdata[1],pmult,&result[1]); } else if(pdata[0]!='-'&&pmult[0]=='-')//当第一个为正,第二个为负时,相乘结果第一位必为'-',再调用函数multiply[] { result[0]='-'; multiply(pdata,&pmult[1],&result[1]); } else if(pdata[0]=='-'&&pmult[0]=='-')//当两个数均为负整数时,相当于两个正整数相乘,调用函数multiply[] { multiply(&pdata[1],&pmult[1],result); } return result; }