1011 A+B 和 C
给定区间 [−231,231] 内的 3 个整数 A、B 和 C,请判断 A+B 是否大于 C。
输入格式:
输入第 1 行给出正整数 T (≤10),是测试用例的个数。随后给出 T 组测试用例,每组占一行,顺序给出 A、B 和 C。整数间以空格分隔。
输出格式:
对每组测试用例,在一行中输出 Case #X: true 如果 A+B>C,否则输出 Case #X: false,其中 X 是测试用例的编号(从 1 开始)。
输入样例:
4
1 2 3
2 3 4
2147483647 0 2147483646
0 -2147483648 -2147483647
输出样例:
Case #1: false
Case #2: true
Case #3: true
Case #4: false
要点:
long long的范围是完全可以的,这很简单就不赘述了。
分享一下使用字符串模拟加法的方式,因为我不想再单独写一个减法函数,所以利用计算机编码中补码的思想,减法变为加上补数,这样只留一个加法函数就可以了,同时也不必区分加数的正负,这很方便。
注意,我们直接用十进制补码就可以,因为补码方法是不区分进制的,而且我们是在编程环境中,所以硬件电路高低电平的误差限制不到我们,二进制没有必要。
步骤:
- 首先估算一下字长(要容纳三个数的和,至少需要的位数)。
231-1是int能表示的最大值,21亿多,所以:
3*231 > 63亿 > 50亿-1 = (1010 /2) - 1
3*231 < 66亿 < 500亿-1 = (1011 /2) - 1
因此字长N取11。 - 对于一个正数,我们直接把它对齐成11位即可;对于一个负数,将它的末位取10的补数,其余各位取9的补数。
- 加法函数采用最简单的串行进位的方式,设置一个carry当进位,按位相加再取模即可,只保留11位。
- 最后得到的结果是A+B-C的补码,只要最高位不超过4,同时不等于0,它就是一个正数,输出“true”。
使用long long类型的代码:
18ms,440KB
#include<iostream>
using namespace std;
int main()
{
int T;
cin >> T;
for(int i=0; i<T; ++i) {
long long A, B, C;
cin >> A >> B >> C;
if(A+B > C) {cout << "Case #" << i+1 << ": true" << endl;}
else {cout << "Case #" << i+1 << ": false" << endl;}
}
return 0;
}
更快速的十进制补码加法代码:
6ms,456KB
#include <iostream>
#include <string>
#define N 11 //字长
using namespace std;
void ten_complement(string&, string&); //转换为补码
string add(string&, string&, string&); //加法函数
int main()
{
int T;
cin >> T;
for(int i=0; i<T; ++i) {
string A, B, C;
string a(N,'0'), b(N,'0'), c(N,'0'), sum(N,'0');
cin >> A >> B >> C;
if(C[0] == '-') {C.erase(0, 1);} //使C变为相反数
else {C.insert(0, 1, '-');}
ten_complement(A, a);
ten_complement(B, b);
ten_complement(C, c);
sum = add(a, b, c);
string zero(N, '0');
if(sum[0]<'5' && sum!=zero) { //和的最高位数字不能超过4,同时也不能是0
cout << "Case #" << i+1 << ": true" << endl;
}
else {cout << "Case #" << i+1 << ": false" << endl;}
}
return 0;
}
void ten_complement(string& S, string& s)
{
int l = S.size() - 1;
for(int i=l, j=N-1; i>=0 && j>=0; --i, --j) {
if(S[0] == '-') {
if(i) { //末位取10的补数,其余位取9的补数
s[j] = (i==l) + 9 + 2*'0' - S[i];
}
else {
s[j] = 9 + '0';
i = 1; //i到首位之后,停止后退
}
}
else {s[j] = S[i];} //正数的补码即为本身
}
}
string add(string& a, string& b, string& c)
{
string sum(N, '0');
char carry = '0';
for(int i=N-1, x; i>=0; --i) {
x = a[i] + b[i] + c[i] + carry - 4*'0';
sum[i] = x % 10 + '0';
carry = x / 10 + '0';
}
return sum;
}