目录
一、大数加法
#include<stdio.h>
#include<string.h>
/*大数加法
大数是存放在字符数组里的,毫无疑问,如果两个数位数不一样
要实现个十百位对齐 因此 1、得实现两个字符数组逆序存放
2、存放好后相应位数相加(字符相加会怎么样,如何处理) 并且处理进位
//若c[i]=a[i]+b[i];
//字符相加,做的实际上是整数运算,例如'1'+'9'对应ascii是49+57
//直接用字符去相加较为麻烦,最好可以接一个桥梁中间站 即整型的 va vb vc
//把当前字符数组的字符元素转换成数字再相加
*/
void bigsum(char *a,char *b,char *c);
void ni(char *a);
void swap(char *a,char*b);
int main(void)
{
int i;
char a[201];
char b[201];
char c[201];
scanf("%s",a);
scanf("%s",b);
//1 逆序存放 对齐位数
ni(a);
ni(b);
//2 对应位数相加 对于哪个字符串的位数更多,用lenc来解决
bigsum(a,b,c);
//3 逆序输出
ni(c);
for(i=0;i<strlen(c);i++){
printf("%c",c[i]);
}
}
void ni(char *a){
int len=strlen(a);
int i;
for(i=0;i<len/2;i++){
swap(&a[i],&a[len-i-1]);
}
}
void bigsum(char *a,char *b,char *c){
int i;
int lena=strlen(a);
int lenb=strlen(b);
int lenc=lena>lenb?lena:lenb;
int x=0;//进位的数目
int va=0,vb=0,vc=0;
for(i=0;i<lenc;i++){
//这时又有一个问题,如果一个数组已经计算完位数了,后面是'\0',而另外一个数还没到尽头
//如果还是让va=a[i]-'0' 如果a[i]是'\0' 对应ascii是0 则会导致va=0-48=-48。故需要用加一个判断
va=i<lena?a[i]-'0':0; //字符型转换为整型数字
vb=i<lenb?b[i]-'0':0;
//当前i是否还是小于lena或lenb的?是 则还有数字,可以用其相减,否则应该让va或vb=0
vc=va+vb+x;
//把ab数组的字符变成数字,方便于在c处相加
if(vc>=10){
vc=vc%10; //如果vc大于10.计算vc剩下的个位数
c[i]=vc+'0';
x=1; //计算进位
} else{
x=0;
c[i]=vc+'0';//整型数字转换为字符型
}
}
//循环结束后,还需要判断进位标志x是否为0,若不为0,
//说明最后一次加和也大于0,但是由于i=lenc了,恰好在c[lenc]处设置为'1'
if(x!=0){
c[lenc]='1';
}
}
void swap(char *a,char*b){
char c;
c=*a;
*a=*b;
*b=c;
}
二、大数减法
#include<stdio.h>
#include<string.h>
void swap(char* a,char* b){
char c;
c=*a;
*a=*b;
*b=c;
}
void ni(char* a){
int i;
int len=strlen(a);
for(i=0;i<len/2;i++){
swap(&a[i],&a[len-1-i]);
}
}
void bigminus(char* a,char* b,char* c){
int lena,lenb,lenc;
int va,vb,vc;
int x=0;
int i;
lena=strlen(a);
lenb=strlen(b);
for(i=0;i<lena;i++){
va=a[i]-'0';
vb=i<lenb?b[i]-'0':0;
vc=va-vb-x;
if(vc<0){
x=1;
c[i]=vc+10+'0';
}else{
x=0;
c[i]=vc+'0';
}
}
}
int main(void){
int i;
char a[201];
char b[201];
char c[201];
scanf("%s",a);
scanf("%s",b);
ni(a);
ni(b);
bigminus(a,b,c);
ni(c);
for(i=0;i<strlen(c);i++){
printf("%c",c[i]);
}
}
三、大数乘法
#include<stdio.h>
#include<string.h>
void swap(char* a,char* b){
char c;
c=*a;
*a=*b;
*b=c;
}
void ni(char* a){
int i;
int len=strlen(a);
for(i=0;i<len/2;i++){
swap(&a[i],&a[len-1-i]);
}
}
void mult(char* a,char* b,char* c){
int i,j;
int x;
int lena,lenb;
lena=strlen(a);
lenb=strlen(b);
int va=0,vb=0,vc=0;
//因为乘法是 b数的个位乘以 a数的个位、十位、百位等等,b数的十位乘以a数的个位、十位、百位等等,以此类推
//因此需要嵌套循环
for(i=0;i<lenb;i++){
x=0;
for(j=0;j<lena;j++){
va=a[j]-'0';
vb=b[i]-'0';//把每一位的字符变成数字!
if(c[i+j]!=0){//预防操作:a数的j位乘以b数的i位,最多到达c数的i+j位 因此需要检查i+j位是否不为0
vc=c[i+j]-'0';
}else{
vc=0;
}
vc=va*vb+x+vc;
x=vc/10; //进位数
c[i+j]=vc%10+'0'; //数字变字符
//为什么一定是i+j位呢?
/*我们来思考一下, 第一轮i=0,c[i+j]相当于在0的基础上只决定于 j
第二轮 i=1,相当于在1的基础上只决定于j
第三轮 i=2,相当于在2的基础上只决定于j
例如 1234x5678 1234:a数 5678:b数
1234 a数
x 5678 b数
----------
9872 结果占据数组的0123位 第一轮 i=0指向8 j=0-3内层循环从4到1
8538 结果占据数组的1234位 第二轮 i=1指向7 j=0-3内层循环从4到1
7404 结果占据数组的2345位 第三轮 i=2指向6 j=0-3内层循环从4到1
6170 结果占据数组的3456位 第四轮 i=3指向5 j=0-3内层循环从4到1
写到这里应该知道为什么是c[i+j]
*/
}
if(x>0){
c[i+lena]=x+'0';
}
}
}
int main(void){
int i;
char a[201]={0};
char b[201]={0};
char c[402]={0};
scanf("%s",a);
scanf("%s",b);
ni(a);
ni(b);
mult(a,b,c);
ni(c);
for(i=0;i<strlen(c);i++){
printf("%c",c[i]);
}
}
四、阶乘计算(例如66!)
#include<stdio.h>
#include<string.h>
void swap(char* a,char* b){
char c;
c=*a;
*a=*b;
*b=c;
}
void ni(char* a){
int i;
int len=strlen(a);
for(i=0;i<len/2;i++){
swap(&a[i],&a[len-1-i]);
}
}
//数组和 k 相乘
void multi(char* a,int k){
int i;
int len;
int v=0;//表示数组当前位置的数与乘数k乘法结果
int x=0;
len=strlen(a);
for(i=0;i<len;i++){
v=(a[i]-'0')*k+x;
x=v/10;
a[i]=v%10+'0';
}
//遍历结束后,但可能x中的值不为0,仍需要在数组向前填充
while(x>0){
a[len]=x%10+'0';
len++;
x=x/10;
}
//循环数组的每一位数字,计算当前位置的数字与乘数的乘法结果
}
int main(void){
char a[35661]={0};
int i;
int n;
scanf("%d",&n);
a[0]='1';
for(i=1;i<=n;i++){
multi(a,i);
} // 循环 数组的数不断与i相乘,得到阶乘
ni(a);
for(i=0;i<strlen(a);i++){
printf("%c",a[i]);
}
}