洛谷 P2142 高精度减法

洛谷 P2142 高精度减法题目描述 高精度减法 输入格式 两个整数 a b 第二个可能比第一个大 输出格式 结果 是负数要输出负号 思路 debug 的艰难过程 前天刚刚学会了高精度加法 其实高精减的思路和加法类似 只是多加了借位的操作

大家好,我是讯享网,很高兴认识大家。

题目描述

高精度减法。

输入格式

两个整数 a,b(第二个可能比第一个大)。

输出格式

结果(是负数要输出负号)。

思路(debug的艰难过程)

前天刚刚学会了高精度加法,其实高精减的思路和加法类似,只是多加了借位的操作。基本步骤还是反向构造数组->模拟竖式减法->倒序输出。但有两个点需要注意:

1.由于a,b的大小关系不确定,所以我的思路是统一转换成a>b的模式,若a<b则交换a,b并输出负号。一开始比较a和b的时候我是这样做的:


讯享网

if(strcmp(s1,s2)<0)

讯享网

然后有3个点WA了,看了测试点样例(30141,8160)后发现只用strcmp函数完全不行,因为strcmp函数是自左向右逐个字符比较,出现不同的字符则返回s1[i]-s2[i]的值。在这个样例中s1[0]=='3',s2[0]=='8',strcmp(s1,s2)<0,需要交换两字符串,然而观察发现a>b,并不需要交换。看了dalao的代码才发现这个比较方法如此巧妙:

讯享网if(strlen(s1)<strlen(s2)||strlen(s1)==strlen(s2)&&strcmp(s1,s2)<0)

2.输出答案时,由于答案的位数在strlen(s1)~1之间,我们将输出的范围定在c[1]-c[strlen(s1)],那么如果c的位数小于strlen(s1),答案就会出现前导0,这时我们就需要解决消去前导0的问题。我的想法是,第一次出现非0数时进行标记,若c[i]==0&&flag则证明该0不是前导0,进行输出:

int flag=0; for(int i=strlen(s1);i>0;i--){ if(c[i]!=0){ flag=1;printf("%d",c[i]); } if(c[i]==0&&flag) printf("%d",c[i]); }

还有一种情况没有解决:如果a==b,只需要输出0怎么办。上面代码的flag可以轻松解决这个问题:如果循环结束时flag==0,那么证明答案中只有0,也就是a==b,此时输出0即可。

讯享网if(flag==0) printf("0");

完整代码:

#include<stdio.h> #include<string.h> int main(){ char s1[11000],s2[11000];//约定a>b int a[11000]={0},b[11000]={0}; scanf("%s %s",s1,s2); if(strlen(s1)<strlen(s2)||strlen(s1)==strlen(s2)&&strcmp(s1,s2)<0){//巧妙比较两数大小,不能简单地用字符串比较函数 char tem[11000]; strcpy(tem,s1); strcpy(s1,s2); strcpy(s2,tem); printf("-"); } for(int i=1;i<=strlen(s1);i++){ a[i]=s1[strlen(s1)-i]-'0'; } for(int i=1;i<=strlen(s2);i++){ b[i]=s2[strlen(s2)-i]-'0'; } int c[11000]={0}; for(int i=1;i<=strlen(s1);i++){ if(a[i]-b[i]<0){ a[i]+=10;a[i+1]--; } c[i]=a[i]-b[i]; } int flag=0; for(int i=strlen(s1);i>0;i--){ if(c[i]!=0){ flag=1;printf("%d",c[i]); } if(c[i]==0&&flag) printf("%d",c[i]); } if(flag==0) printf("0"); return 0; } 

小讯
上一篇 2025-01-10 13:08
下一篇 2025-03-14 23:58

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/119643.html