题目描述
如题
解题思路
手写加减法最重要的就是捋清进位和借位的逻辑,其实就是模拟算式运算。
- 加法的处理思路是将加数1当前位 + 加数2当前位 + 进位,用得到的数值 mod 进制得到当前位的计算结果,再判断是否有进位。
- 减法的思路是用被减数的当前位 - 借位 - 减数的当前位,如果 (被减数 - 借位) 小于 减数当前位,则产生借位,当前位的计算结果是 借位后的数值 - 减数当前位。
- 在处理减法时,可以选择用大数减小数,得到的结果再取反。下面的程序是基于字符串实现的,取反就是在字符串首部添加 ‘-’。
- 再考虑输入的数字有可能为负数,那么有如下的情况(假设 a 和 b都为正数):
//加法
a + b = a + b;
a + (-b) = a - b; //用减法计算加法
(-a) + b = b - a;//同上
(-a) + (-b) = -(a + b);//最后添加‘-’
//减法
a - b = a - b;
a - (-b) = a + b;//用加法计算减法
(-a) - b = -(a + b);//同上
(-a) - (-b) = b - a;
实现
代码写的应该有点臃肿,没做进一步精简。
测试了几个自己想的测试用例是可以通过的,测试用例的格式示例:-4nm + 5nn(注意空格)或者 -4nm - 5nn
# include<iostream>
# include<string>
# include<algorithm>
using namespace std;
int scale = 24;
string myplus(string& a,string& b);
string mysub(string& a, string& b);
int convert(char x);//字符转整型数字
char rconvert(int x);//整型数字转字符,0-23 -> 0-9 & a-n
bool bigger(string str1, string str2);
int convert(char x)
{
if (x >= '0' && x <= '9')
return x - '0';
else{
return x - 'a' + 10;
}
}
char rconvert(int x)
{
if (x <= 9)
return '0' + x;
else
return 'a' + x - 10;
}
bool bigger(string str1, string str2){//str1是否大于str2
size_t s1len = str1.length(), s2len = str2.length();
if (s1len > s2len)
return true;
else if (s1len == s2len)
return str1 > str2;
else return false;
}
string myplus(string& a, string& b)
{
string res;
if (a[0] == '-' && b[0] == '-')//(-a)+(-b)=-(a+b)
{
res = myplus(a.substr(1, a.length() - 1), b.substr(1, b.length() - 1));
res.insert(0, 1, '-');
}
else if (a[0] == '-' || b[0] == '-')//a+(-b)=a-b, (-a)+b=b-a;
{
if (a[0] == '-'){
a = a.substr(1, a.length() - 1);
res = mysub(b, a);
}
else if (b[0] == '-'){
b = b.substr(1, b.length() - 1);
res = mysub(a, b);
}
}
else{//a和b都是正数
size_t alen = a.length(), blen = b.length(), srt = min(alen, blen), lng = max(alen, blen), i;
string &tem = b;
if (alen > blen)
tem = a;
int flag = 0;
char c;
for (i = 0; i < srt; ++i){
int end = convert(a[alen - 1 - i]) + convert(b[blen - 1 - i]) + flag;
if (end >= scale)
{
c = rconvert(end - scale);
flag = 1;
}
else{
c = rconvert(end);
flag = 0;
}
res.insert(0, 1, c);
}
for (i = srt; i < lng; ++i)
{
res.insert(0, 1, rconvert((convert(tem[lng -srt-1]) + flag) % scale));
flag = (convert(tem[lng - srt - 1]) + flag) / scale;
}
if (flag != 0) res.insert(0, 1, rconvert(flag));
}
return res;
}
string mysub(string& a, string& b){//注意最高位是0的情况
string res;
if (a[0] == '-' && b[0] == '-'){//(-a)-(-b)=b-a
a = a.substr(1, a.length() - 1);
b = b.substr(1, b.length() - 1);
res = mysub(b, a);
}
else if (a[0] == '-' || b[0] == '-'){//a-(-b)=b+a, (-a)-b = -(a+b);
if (a[0] == '-'){
a = a.substr(1, a.length() - 1);
res = myplus(a, b);
res.insert(0, 1, '-');
}
else if (b[0] == '-'){
b = b.substr(1, b.length() - 1);
res = myplus(a, b);
}
}
else{//a和b都是正数
bool isneg = true;
if (bigger(b, a)) {
isneg = false;
res = mysub(b, a);
res.insert(0, 1, '-');
}
else{//a和b都是正数且a>b
int flag = 0;
size_t s2len = b.length(), s1len = a.length();
size_t srt = s2len, lng = s1len, big, sma, i;
char c;
for (i = 0; i < srt; ++i)
{
big = convert(a[s1len - 1 - i]) - flag;
sma = convert(b[s2len - 1 - i]);
if (big >= sma)//有可能为0
{
flag = 0;
c = rconvert(big - sma);
}
else if (big < sma)
{
flag = 1;
c = rconvert(big + scale - sma);
}
res.insert(0, 1, c);
}
for (i = srt; i < lng; ++i)
{
big = convert(a[s1len - 1 - i]) - flag;
flag = 0;
res.insert(0, 1, rconvert(big));
}
i = 0;
while (i < res.length() && res[i] == '0') ++i;
if (i == res.length()) res = "0";
else{
res = res.substr(i, res.length() - i);
}
}
}
return res;
}
int main(){
string str1, op, str2, rest;
while (cin >> str1 >> op >> str2){
if (op == "+")
rest = myplus(str1, str2);
else if (op == "-")
rest = mysub(str1, str2);
else{
cout << "operator invalid" << endl;
continue;
}
cout << rest << endl;
}
system("pause");
}
废话
之前做笔试的时候紧张得思维混乱,现在克服了笔试时的紧张情绪,可以专注想问题了。但还是过不了面试的手撕代码关,emm,什么时候再进阶一下。
就在此处悄咪咪表白一下 Ali 的面试官,他们都是大可爱!感恩,手动比心。