[问题描述]
编写程序实现两个超长正整数(每个最长80位数字)的减法运算。
[输入形式]
从键盘读入两个整数,要考虑输入高位可能为0的情况(如00083)
1.第一行是超长正整数A;
2.第二行是超长正整数B;
[输出形式]
输出只有一行,是长整数A减去长整数B的运算结果,从高到低依次输出各位数字。要求: 若结果为0,则只输出一个0;否则输出的结果的最高位不能为0,并且各位数字紧密输出。
[输入样例]
234098
134098703578230856
[输出样例]
-134098783577995958
[样例说明]
进行两个正整数减法运算,234098 - 134098703578230056 = - 134098703577995958。
[思路分析]
题目要求为超长正整数的减法运算,容易知道整型变量无法完成此操作,所以大体思路:考虑用两个字符数组储存,用两数组的ASCII码进行运算,然后判断符号,进行输出。
具体步骤:
- 先定义两个字符数组代替整型储存这两个整数;
- 考虑字符数组ASCII码相减需要对齐位数,排除数字开头为0的情况,于是先用循环将每个数组前面的0都消去,使得两数组代表的数字都是非零数开头的;
- 由于字符数组ASCII码相减从低位开始会更为容易,于是将处理0以后的两个数组均调用逆序函数逆序存放,使得对应的数字为低位在前高位在后,由低到高依次运算,这样容易处理借位情况;
- 定义字符数组的运算函数,将两个字符数组对应位的ASCII码分别相减,直接将结果保存在整型数组中,通过判断整型数组每个数的正负来确定是否借位,如果小于0则借位,则它本身加十,并且高位即下一个数减去一来借位,执行完此操作,整型数组内存放的即超长整数的差的绝对值的逆序;
- 由于2)已经将两个字符数组开头的零去掉了,因此,位数不同时可以很容易由字符数组的长度来判断两个整数的大小,位数相同的时可以通过第一个不同字符的ASCII码的数值的大小来判断两个整数的大小,通过不同的传递顺序把两个字符数组传递给运算函数,并判断输出时是否加负号;
- 确定正负号以后的最后一步即将之前保存的整型数组按照倒序输出在符号后边即可。
[代码实现]
#include<stdio.h>
#include<string.h>
int c[100];
int judge(char a[],char b[])
{if (strlen(a) > strlen(b))return 1;else if (strlen(a) < strlen(b))return 0;elsefor (int i = 0; i < strlen(a); i++)if (a[i] > b[i])return 1;return 0;
}void minus(char a[], char b[])
{char t;for (int i = 0; i < strlen(a) / 2; i++){t = a[i];a[i]=a[strlen(a) - 1 - i];a[strlen(a) - 1 - i] = t;}for (int i = 0; i < strlen(b) / 2; i++){t = b[i];a[i] = a[strlen(b) - 1 - i];a[strlen(b) - 1 - i] = t;}for(int i=0;i<strlen(a);i++){if (i < strlen(b))c[i] = a[i] - b[i];elsec[i] = a[i] - '0';}for (int i = 0; i < strlen(a) - 1; i++)if(c[i]<0){c[i] += 10;c[i + 1] -= 1;}
}void deletechar(char a[])
{int t = 0, len;while (a[t] == '0')t++;len = strlen(a) - t;for (int i = 0; i <= len; i++)a[i] = a[i + t];
}
int main()
{char a[100], b[100];gets(a);gets(b);deletechar(a);deletechar(b);if (judge(a, b))minus(a, b);else{printf("-");minus(b, a);}int i = 100;while (c[i] == 0 && i != 0)i--;for (int j = i; j >= 0; j--)printf("%d", c[j]);
}