【高精度计算】
今天是开博客的第一天,特此庆祝一下,也激励一下自己要更加努力。机会总是留给勤奋努力的人的。从今天开始我希望在博客中记录自己刷OJ的一些感想和体会 ,现在自己还很一般,希望通过博客记录自己成长的一点一滴。
今天开始我会研究关于高精度计算的相关题目。刚刚做了两道题,现在一一贴出来。
- UVA 424 Integer Inquiry
高精度求和:
输入:每行输入一个不超过100位的数字,当输入为0时输入结束
输出:各行数字的和
分析:看到这道题目,立马可以想到要想表示100位的数字,int 和long long都是无法完成的。为了要完成任务,我们可以想到使用数组或者字符串。数组的优点是:数组的各位可以任意进行计算,但是数组的输入不方便,需要用空格等间隔开;而字符串的优点恰好相反,字符串的输入十分方便,但是按位进行计算比较麻烦。因此,我们可以采用以字符串的方式进行输入,最后将输入的字符串按位转化为数组中的元素进行运算。
其中需要注意的就是相加函数的编写。在该程序中,将数组第一个元素定义为数字长度。主要是使用按位相加,最终根据每一位是否大于等于10 来进行进位操作。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[120][120];
int number[120][120]; //数组最好开得大一些
void add(int number1[],int number2[])
{
if(number1[0]<number2[0])
number1[0]=number2[0]; //保证number1是更大的,因为最终的结果要保存在number1中
int i;
for(i=1;i<=number1[0];i++)
{
number1[i]+=number2[i]; //每一位都各自相加
if(number1[i]>=10)
{
number1[i+1]+=number1[i]/10; //如果某一位大于等于10 就要进位
number1[i]%=10;
}
}
if(number1[number1[0]+1]>0) //最后判断最高位是否产生进位,如果进位了,就要在记录长度的元素加1
number1[0]++;
}
int main()
{
int i=0,j,k;
while(scanf("%s",s[i])!=EOF)
{
if(strcmp(s[i],"0")==0) //这里是代表输入为0时自动跳出循环,结束输入
{
break;
}
i++;
}
for(j=0;j<i;j++)
{
number[j][0]=strlen(s[j]); //将数组的第一个元素记录字符串的长度
for(k=1;k<=number[j][0];k++)
number[j][k]=s[j][number[j][0]-k]-'0'; //将字符串的每一位字符转化为整数赋值给数组,但是要注意最好采用倒序赋值,因为在数组运算会产生进位
//利用倒序会很方便
}
for(j=1;j<i;j++)
add(number[0],number[j]); //进行相加,值存放在number[0]中
for(j=number[0][0];j>=1;j--)
printf("%d",number[0][j]); //逆序打印输出
printf("\n");
return 0;
}
解题的时候,我出现了一个问题:
在第一次上交OJ时,出现了WA,主要是粗心,因为当时使用了freopen重定向至文本输入,判断完成时没有删除就提交了。
最后删除过后再提交就AC了。
乘积.
输入:两个整数x,y,(0<=x,y<10^250)
输出:两个数的积.
分析:这道题由于是要求250位的乘积,所以依然要用到高精度,分析当时类似于上题
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[10][300];
int str[10][300];
int res[600];
void mutiply(int *a,int *b)
{
memset(res,0,sizeof(res));
if((a[0]==1&&a[1]==0)||(b[0]==1&&b[1]==0)) //如果有一个数是0的话,结果就是0,退出函数
{
res[0]=1;
res[1]=0;
return;
}
int i,j;
for(i=1;i<=a[0];i++)
for(j=1;j<=b[0];j++)
res[i+j-1]+=a[i]*b[j]; //两个数相乘,先按位进行相乘
res[0]=a[0]+b[0]-1; //最后的长度为两个数字长度之和减1
for(i=1;i<=res[0];i++)
{
if(res[i]>=10) //如果某一位大于等于10,就进位
{
res[i+1]+=res[i]/10;
res[i]%=10;
}
}
while(res[res[0]+1]>0)
res[0]++;
return;
}
int main()
{
memset(s,0,sizeof(s)); //将数组置0
int i=0;
while(fgets(s[i],sizeof(s[i]),stdin)!=NULL)
{
int j;
str[i][0]=strlen(s[i])-1;
for(j=1;j<=str[i][0];j++)
{
str[i][j]=s[i][str[i][0]-j]-'0';
}
i++;
if(i==2)
{
mutiply(str[0],str[1]); //相乘,结果赋值给res
for(j=res[0];j>=1;j--)
printf("%d",res[j]);
printf("\n");
i=0;
memset(s,0,sizeof(s));
}
}
return 0;
}
解题时,第一次提交给OJ时出现WA,主要原因是没有对输入的数字是0进行判断,如果输入1234*0,按照我的思路结果是0000,与答案不符。所以必须在计算前进行判断,如果是0的话就直接退出即可。
第二次提交时就AC了。