数学最重要 【BUPT_OJ 1001】

http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1001&submit=Go

Description
Calculate A-B

Input
Two integer a and b(-10^100 < a,b < 10^100)

Output
Output a-b

Sample Input

1 2


Sample Output

-1

 

     这个题可让我愁死了。做了两天才做出来。看看成功率,这个题确实比较难。

     开始以为和1000题一样简单,看了以后傻眼了,100位的数字减法,这个没有东西可以存贮啊。

int a[102],b[102],result[102]; 

     在第一时间想到了用数组来存储这个东西,用102位,其中第0位是符号位。怎么读入呢? 开始使用了cin<<函数,但是有一个不好,cin<<函数没有单独读取/n换行符的能力,而在进行判断的时候需要用这几个字符,所以权衡之后还是使用了getchar()函数来实现这个功能。

     由于读取的时候会倒着输入,所以需要有一些简单的处理,先将数组填满为“101”的数值,然后读入数据,循环搜索到不是“101”的时候就可以得到这个数据的位数。然后将他们交换位置即可得到结果。

void read(int *p){ for(i=0;i<=101;i++) p[i]=100; p[0]=1;i=101; while((num!=' ')&&(num!='/n')){ num=getchar(); if (num=='-') {p[0]=0;continue;} if (num<='9'&&num>='0') {p[i]=int(num)-48;i--;} } //读入数据 for (i=1;(i<=101)&&(p[i]==100);i++); //检查有多少位数字 ch1=i;ch2=101; for (j=1;j<i;j++) p[j]=0; while(ch1<=ch2){ //交换顺序 swap(p[ch1],p[ch2]); ch1++;ch2--; } num='x'; } 

     由于经验少,所以这次并没有想到应该用什么方式表示负数。如果是直接相减减出来的负数还好说,A,B如果是负数就没有办法了。这时候我只能用我们平时算术的经验,比如正数减去负数等于两个正数相加——这样的方法来解决,编写了一个check函数,用来将输入进来的数字进行分类。

void check(){ if ((a[0]==1)&&(b[0]==1)){ //如果a正b正 for (i=1;i<=101;i++) { if (a[i]>b[i]) {jian(a,b);result[0]=1;break;} if (a[i]<b[i]) {jian(b,a);result[0]=0;break;} } } if ((a[0]==1)&&(b[0]==0)){ //如果a正b负 jia(a,b);result[0]=1; } if ((a[0]==0)&&(b[0]==1)){ //如果a负b正 jia(a,b);result[0]=0; } if ((a[0]==0)&&(b[0]==0)){ //如果a正b正 for (i=1;i<=101;i++) { if (a[i]>b[i]) {jian(a,b);result[0]=0;break;} if (a[i]<b[i]) {jian(b,a);result[0]=1;break;} } } } 

     这样就把减法换成了我们平时所想的方法了。而且考虑的符号的问题。然后是其中加减法的实现函数。

void jian(int *p,int *q){ //减法函数 for (i=101;i>=1;i--){ if (p[i]-q[i]>=0) result[i]=p[i]-q[i]; else { int k;k=i; result[k]=p[k]-q[k]+10; while (p[k-1]==0){ //借位 p[k-1]=9; k--; } p[k-1]--; } }} void jia(int *p,int *q){ //加法函数 for (i=101;i>=1;i--){ if (p[i]+q[i]<10) result[i]=p[i]+q[i]; else { result[i]=p[i]+q[i]-10; //进位 p[i-1]++; } } } 

 

 

     这其中要注意的就是对于进位和借位的计算。仔细想想并不难。

     最后将结果的正负判断一下输出,再判断一下是零的情况,就完成了整个程序。 全代码如下:

 

#include<iostream> using namespace std; int a[102],b[102],result[102]; int i=100,ch1,ch2,j,flag=0; char num='x'; void swap(int &x,int &y){ int c; c=x; x=y; y=c; } void read(int *p){ for(i=0;i<=101;i++) p[i]=100; p[0]=1;i=101; while((num!=' ')&&(num!='/n')){ num=getchar(); if (num=='-') {p[0]=0;continue;} if (num<='9'&&num>='0') {p[i]=int(num)-48;i--;} } //读入数据 for (i=1;(i<=101)&&(p[i]==100);i++); //检查有多少位数字 ch1=i;ch2=101; for (j=1;j<i;j++) p[j]=0; while(ch1<=ch2){ //交换顺序 swap(p[ch1],p[ch2]); ch1++;ch2--; } num='x'; } void jian(int *p,int *q){ //减法函数 for (i=101;i>=1;i--){ if (p[i]-q[i]>=0) result[i]=p[i]-q[i]; else { int k;k=i; result[k]=p[k]-q[k]+10; while (p[k-1]==0){ //借位 p[k-1]=9; k--; } p[k-1]--; } }} void jia(int *p,int *q){ //加法函数 for (i=101;i>=1;i--){ if (p[i]+q[i]<10) result[i]=p[i]+q[i]; else { result[i]=p[i]+q[i]-10; //进位 p[i-1]++; } } } void check(){ if ((a[0]==1)&&(b[0]==1)){ //如果a正b正 for (i=1;i<=101;i++) { if (a[i]>b[i]) {jian(a,b);result[0]=1;break;} if (a[i]<b[i]) {jian(b,a);result[0]=0;break;} } } if ((a[0]==1)&&(b[0]==0)){ //如果a正b负 jia(a,b);result[0]=1; } if ((a[0]==0)&&(b[0]==1)){ //如果a负b正 jia(a,b);result[0]=0; } if ((a[0]==0)&&(b[0]==0)){ //如果a正b正 for (i=1;i<=101;i++) { if (a[i]>b[i]) {jian(a,b);result[0]=0;break;} if (a[i]<b[i]) {jian(b,a);result[0]=1;break;} } } } int main(){ read(a); read(b); check(); for (i=1;(result[i]==0)&&(i<=101);i++); if ((i==102)&&(result[101]==0)) cout<<0; else { if (result[0]==0) cout<<'-'; for (;i<=101;i++) cout<<result[i]; } return 0; }  

 

 

    PS:有高人想到了补码的方式,这样可以让十进制加减法统一,大大减少思考的难度。

    哎  编程还是数学最重要啊!

你可能感兴趣的:(数学最重要 【BUPT_OJ 1001】)