using namespace std;
typedef unsigned long L;
// 是否开启调试模式
//
// 只用到等于和加
class bigNum {
unsigned char* aPosNums;
bool isOne;
public:
L numLen, saveSize;
bigNum(string str, L size) {
isOne = false;
cout << "创建数字,以文字内容:" << str << ",长度为:" << str.length() << ",存储大小为:" << size << endl;
aPosNums = new unsigned char[size];
puts("大小分配完毕");
saveSize = size;
L i;
// 输入的文字分位存在数字组中,遍历法,一字占一数
for (i = 0/*长整可以让数字到四十亿长*/; i < str.length()/*为什么是函数不是属性*/; i++) {
aPosNums[i] = str[i] - '0';
}
numLen = i;
puts("创建完毕,结果内容检测:");
for (i = 0; i < numLen; i++) {
cout << aPosNums[i] << ' ';
}
putchar('\n');
}
// 下面三运算添加调试显示会让结果不好看,除非在另一个控制台显示,不会
// 只有文字才能用这么大数
string toString() {
string result;
char a[] = "a";
for (L i = 0; i < numLen; i++) {
a[0] = aPosNums[i] + '0';
result.append(a);
}
return result;
}
void operator=(bigNum b) {
for (L i = 0; i < b.numLen; i++) {
aPosNums[i] = b.aPosNums[i];
}
numLen = b.numLen;
if (b.isOne)
delete b.aPosNums;
}
bigNum operator+(bigNum addition) {
// 忘了得复制一个分开
bigNum result(toString(), saveSize);
result.isOne = true;
// 复合太难了,还是分支容易,最大的情况放最外面分
// 三种长度情况,自己更长,加数更长,相等的情况最少见故而放最后
if (result.numLen > addition.numLen) {
// 自己更大,以加数长度为相加遍历终点,从尾部开始计算
L i, i2;// 循环外部需要使用,声明在外面
for (i = addition.numLen - 1, i2 = result.numLen - 1; i > 0/*不可小于零,最后一次额外处理*/; i--, i2--) {
result.aPosNums[i2] += addition.aPosNums[i];
// 相加后溢出处理
if (result.aPosNums[i2] > 9) {
// 只能溢个1
result.aPosNums[i2] -= 10;
result.aPosNums[i2 + 1]++;
}
}
if (result.aPosNums[i2] > 9) {
result.aPosNums -= 10;
// 到头了,进一位
if (i2 == 0) {
for (i = result.numLen; i > 0; i--) {
result.aPosNums[i] = result.aPosNums[i - 1];
}
result.aPosNums[0] = 1;
result.numLen++;
}// 否则继续往左加
else {
do {
i2--;
result.aPosNums[i2]++;
if (result.aPosNums[i2] > 9) {
result.aPosNums[i2] -= 10;
result.aPosNums[i2 - 1]++;
}
} while (i2 != 0);
// 此处用跳转方便还能减少复制粘贴,可是怎得。复制粘贴完全没有必要?
if (result.aPosNums[0] > 9) {
for (i = result.numLen; i > 0; i--) {
result.aPosNums[i] = result.aPosNums[i - 1];
}
result.aPosNums[0] = 1;
result.numLen++;
}
}
}
}
else if (result.numLen < addition.numLen) {
// 才敲了一种情况,还有两种
// 先位移,准备先将加数多出来的部分加入前面
L i, gap = addition.numLen - result.numLen;
for (i = result.numLen - 1; i > 0; i--) {
result.aPosNums[i + gap] = result.aPosNums[i];
}
// 加入前数
result.aPosNums[i + gap] = result.aPosNums[i];
for (i = 0; i < result.numLen; i++) {
result.aPosNums[i] = addition.aPosNums[i];
}
// 后部分相加,除了原来的最高位
for (i = addition.numLen - 1; i > result.numLen; i--) {
result.aPosNums[i] += addition.aPosNums[i];
if (result.aPosNums[i] > 9) {
result.aPosNums[i] -= 10;
result.aPosNums[i - 1]++;
}
}
// 处理溢出传数进位
result.aPosNums[i] += addition.aPosNums[i];
while (i != 0 && result.aPosNums[i] > 9) {
result.aPosNums[i--] -= 10;
result.aPosNums[i]++;
}
// 虽然本来那次位移如果之前能推测出来一次就可以,但这种进位少
if (result.aPosNums[0] > 9) {
// 到底了还要进一位,整体右移让出一位用来进
for (i = addition.numLen; i > 0; i--) {
result.aPosNums[i] = result.aPosNums[i - 1];
}
result.aPosNums[0] = 1;
result.numLen = addition.numLen + 1;
}
else
result.numLen = addition.numLen;
}//否则只能是相等,最简单的?
else {
L i;
// 除最高位相加
for (i = result.numLen - 1; i > 0; i--) {
result.aPosNums[i] += addition.aPosNums[i];
if (result.aPosNums[i] > 9) {
result.aPosNums[i] -= 10;
result.aPosNums[i - 1]++;
}
}
// 最高位特殊处理
result.aPosNums[i] += addition.aPosNums[i];
// 最高位进位,右移补一
if (result.aPosNums[i] > 9) {
result.aPosNums[i] -= 10;
for (i = result.numLen; i > 0; i--) {
result.aPosNums[i] = result.aPosNums[i - 1];
}
result.aPosNums[0] = 1;
result.numLen++;
}
}
return result;
}
};
int main() {
string num1, num2;
cin >> num1 >> num2;
bigNum n1(num1, 40), n2(num2, 40);
cout << (n1 + n2).toString();
}