学习记录 2
大数的存储与运算
c语言中,如果一个数超过了long long int的范围,我们就应该用数组的方式去实现这个大数的存储与运算。
首先我们可以定义一个字符数组char[100] (一般来说,经常用字符数组去接受一个未知长度的数字,只需要减去‘0’即可),之后转化到int number[100]里面去。
运算的算法完全模拟我们的人工计算
1.加法
现在有number[100],number1[100],要实现加法运算。我们可以先把数组里面的数倒过来,也就是用number[0]来存储个位数,number[1] 存储十位数·····这样做的好处在于之后可以用一个循环变量如i就可以把它们的对应位数相加。我们用result[100]来存储结果,result[0]就是number[0]与number1[0]的和,之后再把每个位置的数进位一下就行了。
2.减法
同样先把数倒过来,让对应位置的数相减,如果不够减,就向后借一位。
这样的算法只能够是较大的数减较小的数,不过没有关系,只需要先判断一下谁更大就行了。
3.乘法
一开始应该用一个数组的number[0]去乘另一个number1[0],结果存在result[0]里面.然后乘number1[1],结果存在result[1]里面。直至number[0]把每一个number1里面的元素都乘完,再对number[1]进行类似操作。
笔者在进制转化问题,以及阶乘问题中也经常遇到大数。
如:输入一个字符串(字符串的长度不超过20),对其做如下处理:滤去所有的非十六进制字符后,组成一个新字符串(十六进制形式),然后将其转换为十进制数后输出。
例:
输入: A4 1cDb ACDB
输出: 十六进制:0xA41CDBACDB 十进制:704858795227
这题的关键在于如何生成16的高次幂,首先生成0次幂,也就是1。1次幂只需用16乘以0次幂的每个数,再进位。二次幂就用16乘以一次幂的每个数,再进位······
如:
给n个数字,输出这些数字在二进制下的位数。
如:计算100的阶乘
代码如下
#include<stdio.h> //大数运算器
#define MAX 100
int size,size1;
void carry(int* num);
void add(int* num,int* num1);
void subtract(int* num,int* num1);
void multiply(int* num,int* num1);
int main()
{
char str_number[MAX]={0},str_number1[MAX]={0};
int number[MAX]={0},number1[MAX]={0};
int i,temp,ch;
void (*pf[3])(int* num,int* num1)={add,subtract,multiply};
printf("欢迎使用”孤铉“计算器\n");
printf("请您先输入2个数字\n");
gets(str_number);
gets(str_number1);
for(i=MAX-1;str_number[i]==0;i--);
size=i+1;
for(i=MAX-1;str_number1[i]==0;i--);
size1=i+1;
for(i=0;i<size/2;i++) //从低位到高位
{
temp=str_number[i];
str_number[i]=str_number[size-1-i];
str_number[size-1-i]=temp;
}
for(i=0;i<size;i++)
{
number[i]=str_number[i]-'0';
//printf("%d",number[i]);
}
//printf("\n");
for(i=0;i<size1/2;i++) //从低位到高位
{
temp=str_number1[i];
str_number1[i]=str_number1[size1-1-i];
str_number1[size1-1-i]=temp;
}
for(i=0;i<size1;i++)
{
number1[i]=str_number1[i]-'0';
//printf("%d",number1[i]);
}
printf("请输入您要进行的运算:");
printf("\n加法:0\n减法:1\n乘法:2\n");
while(1)
{
scanf("%d",&ch);
if(ch>=0&&ch<=2)
break;
else
printf("指令错误,请重新输入\n");
fflush(stdin);
}
pf[ch](number,number1);
}
void carry(int* num)
{
int i;
for(i=0;i<MAX;i++)
{
if(num[i]>=10)
{
num[i+1]+=num[i]/10;
num[i]%=10;
}
}
}
void add(int* num,int* num1)
{
int result[MAX]={0};
int i,size;
for(i=0;i<MAX;i++)
result[i]=num[i]+num1[i];
carry(result);
for(i=MAX-1;result[i]==0;i--);
size=i+1;
printf("\n");
for(i=size-1;i>=0;i--)
{
printf("%d",result[i]);
}
}
void subtract(int* num,int* num1) //num-num1
{
int result[MAX]={0};
int i,size_res,flag;
if(size>size1)
flag=1;
if(size<size1)
flag=0;
if(size==size1)
{
for(i=size-1;i>=0;i--)
if(num[i]!=num1[i])
break;
if(num[i]>num1[i]||i==-1)
flag=1;
else
flag=0;
}
if(flag==1)
{
for(i=0;i<MAX;i++)
{
if(num[i]<num1[i])
{
num[i]+=10;
num[i+1]-=1;
}
result[i]=num[i]-num1[i];
}
}
else
{
for(i=0;i<MAX;i++)
{
if(num1[i]<num[i])
{
num1[i]+=10;
num1[i+1]-=1;
}
result[i]=num1[i]-num[i];
}
}
if(flag==0)
printf("-");
for(i=MAX-1;result[i]==0;i--);
size_res=i+1;
for(i=size_res-1;i>=0;i--)
{
printf("%d",result[i]);
}
if(size_res==0)
printf("0");
}
void multiply(int* num,int* num1)
{
int result[MAX]={0};
int i,j,size_res;
for(i=0;i<MAX;i++)
{
for(j=0;j<size1;j++)
result[i+j]+=num[i]*num1[j];
}
carry(result);
for(i=MAX-1;result[i]==0;i--);
size_res=i+1;
for(i=size_res-1;i>=0;i--)
{
printf("%d",result[i]);
}
}
#include<stdio.h>
#include<string.h>
void input_out(char *);
void wash(char *str,int *number);
void multi(int *time,int flag);
void push (int *time);
void add(int *sum,int *number,int *time);
int main()
{
char str[20];
int number[20]={0};
int sum[30]={0};
int time[30];
input_out(str);
wash(str,number);
add(sum,number,time);
printf("\n\n\n");
}
void input_out(char *str_m)
{
char str[20];
int cur,pre;
printf("请输入一个字符串");
gets(str);
for(cur=0,pre=0;str[pre];pre++) //最后一个就是0
{
if('A'<=str[pre]&&str[pre]<='F') str[cur++]=str[pre];
if('a'<=str[pre]&&str[pre]<='f') str[cur++]=str[pre];
if('0'<=str[pre]&&str[pre]<='9') str[cur++]=str[pre];
}
str[cur]=0;
printf("十六进制: 0x%s",str);
strcpy(str_m,str);
}
void wash(char *str,int *number)
{
int i,flag,temp;
for(i=0;str[i]!=0;i++)
{
if(str[i]>='a'&&str[i]<='f')
number[i]=str[i]-'a'+10;
if(str[i]>='A'&&str[i]<='F')
number[i]=str[i]-'A'+10;
if(str[i]>='0'&&str[i]<='9')
number[i]=str[i]-'0';
}
flag=i-1;
for(i=0;i<=flag/2;i++) //从低位到高位排
{
temp=number[i];
number[i]=number[flag-i];
number[flag-i]=temp;
}
}
void multi(int *time,int flag)
{
int i,j;
for(i=0;i<30;i++)
time[i]=0;
time[0]=1;
for(i=0;i<flag;i++)
{
for(j=0;j<29;j++)
time[j]*=16;
push(time);
}
}
void push (int *time)
{
int i;
for(i=0;i<29;i++)
{
if(time[i]>=10)
{
time[i+1]+=time[i]/10;
time[i]%=10;
}
}
}
void add(int *sum,int *number,int *time)
{
int i,j;
for(i=0;i<20;i++) // 第几个number
{
multi(time,i); //对应的16倍数
for(j=0;j<30;j++)
time[j]*=number[i]; //乘以系数
for(j=0;j<30;j++)
sum[j]+=time[j];
push(sum);
}
printf("\n十进制:");
for(i=29;sum[i]==0;i--); //从后开始第一个不为0的数
for(;i>=0;i--)
printf("%d",sum[i]);
}
# include<stdio.h>
#include<stdlib.h>
void multi(int *time,int flag);
void push (int *time);
int main ()
{
char strNumber[1000];
int time[1000];
int i,j,k,flag,sizeStr,sizeTime,n; //k为次数
int *p;
scanf("%d",&n);
p=(int *)calloc(n,sizeof(int));
fflush(stdin);
for(k=0;k<n;k++)
{
for(i=0;i<1000;i++)
strNumber[i]=0;
gets(strNumber);
for(i=999;strNumber[i]==0;i--); //i+1个数字
sizeStr=i+1;
for(i=0;i<sizeStr;i++)
strNumber[i]-='0';
for(flag=1;;flag++)
{
multi(time,flag);
for(i=999;time[i]==0;i--); //i个数字
sizeTime=i+1;
if(sizeTime<sizeStr)
continue;
if(sizeTime>sizeStr)
break;
if(sizeTime==sizeStr)
{
for(j=0;j<sizeTime;j++)
{
if(time[j]!=strNumber[j])
break;
}
}
if(time[j]>strNumber[j])
break;
}
p[k]=flag;
}
for(k=0;k<n;k++)
printf("%d\n",p[k]);
}
void multi(int *time,int flag)
{
int i,j,temp;
for(i=0;i<1000;i++)
time[i]=0;
time[0]=1;
for(i=0;i<flag;i++)
{
for(j=0;j<999;j++)
time[j]*=2;
push(time);
}
for(i=999;time[i]==0;i--); //有i+1个数字
for(j=0;j<(i+1)/2;j++)
{
temp=time[j];
time[j]=time[i-j];
time[i-j]=temp;
}
}
void push (int *time)
{
int i;
for(i=0;i<999;i++)
{
if(time[i]>=10)
{
time[i+1]+=time[i]/10;
time[i]%=10;
}
}
}
#include<stdio.h>
#define MAX 200
void carry(int* num);
int main()
{
int factorial[MAX]={0},i,j,n;
scanf("%d",&n);
factorial[0]=1;
for(i=1;i<=n;i++)
{
for(j=0;j<MAX;j++)
{
factorial[j]*=i;
}
carry(factorial);
}
for(i=MAX-1;factorial[i]==0;i--);
for(;i>=0;i--)
printf("%d",factorial[i]);
}
void carry(int* num)
{
int i;
for(i=0;i<MAX;i++)
{
if(num[i]>=10)
{
num[i+1]+=num[i]/10;
num[i]%=10;
}
}
}