实现两个大整数的相加,首先应该排除直接使用int和long long的方法,这些方法很容易溢出,这里为了方便(是否可以使用更精简的结构存储?)采用char来存储整数,整体思路如下:

1. 对于整数n和m的字符串形式,按照数组索引的从大到小累加计算,直接将结果存储到对应的result字符串中,处理完毕后再将result逆序输出,需考虑0和-的输出情况;

2. 考虑到有负号的情况,一开始就需要判断负号字符,这里将(-,-)和(+,+)统一当成相加操作然后都是负号的话在结尾补上负号,对于(+,-)和(-,+)统一处理成(大-小)的形式然后在结尾补负号;比如对于20-500转换成-(-20+500),对于-500+20准换成-(500-20)。

3. 这里需要使用标志位nTake记录是否进位或借位;

4. 还要考虑是否有异常字符出现,使用全局变量gInvalid记录有无异常。

 #include<stdio.h>
#include<string.h> #define Joshua_OJ bool gInvalid = false; // 0: equal, -1: n less m, 1: n bigger m
int AbsIsEqual(char* n, char* m, int n_start, int n_end, int m_start, int m_end)
{
if ((n_end - n_start) > (m_end - m_start)) return ;
else if ((n_end - n_start) < (m_end - m_start)) return -;
else
{
int i = n_start;
int j = m_start;
while (i <= n_end && j <= m_end)
{
if (n[i] > m[j]) return ;
else if (n[i] < m[j]) return -;
++i;
++j;
}
}
return ;
} void BigNumberAdd(char* n, char* m, char* result)
{
gInvalid = false; if (n == NULL || m == NULL)
{
gInvalid = true;
return;
} int n_index = strlen(n) - ;
int m_index = strlen(m) - ; // 负数特别处理
int n_start = ;
int m_start = ;
int n_signed = ;
int m_signed = ;
if (n[] == '-')
{
n_start = ;
n_signed = -;
}
if (m[] == '-')
{
m_start = ;
m_signed = -;
}
// 如果只有一个负数,转换为大数减小数再取负号,这样方便异号借位相减
bool isResetPosNeg = false;
if (n_signed == && m_signed == -)
{
int tag = AbsIsEqual(n, m, n_start, n_index, m_start, m_index);
if (tag == -)
{
n_signed = - n_signed;
m_signed = - m_signed;
isResetPosNeg = true;
}
else if (tag == )
{
result[] = '';
result[] = '\0';
return;
}
}
else if (n_signed == - && m_signed == )
{
int tag = AbsIsEqual(n, m, n_start, n_index, m_start, m_index);
if (tag == )
{
n_signed = - n_signed;
m_signed = - m_signed;
isResetPosNeg = true;
}
else if (tag == )
{
result[] = '';
result[] = '\0';
return;
}
} int index = ;
int nTake = ;
while (n_index >= n_start || m_index >= m_start)
{
int op1, op2;
op1 = op2 = ; if (n_index >= n_start && (n[n_index] < '' || n[n_index] > ''))
{
gInvalid = true;
return;
}
if (m_index >= m_start && (m[m_index] < '' || m[m_index] > ''))
{
gInvalid = true;
return;
} if (n_index >= n_start) op1 = n[n_index] - '';
if (m_index >= m_start) op2 = m[m_index] - '';
if (n_signed == && m_signed == -) op2 = m_signed * op2;
else if (m_signed == && n_signed == -) op1 = n_signed * op1; int nSum = op1 + op2 + nTake;
if (nSum >= )
{
nSum -= ;
result[index] = nSum + '';
nTake = ;
}
else if (nSum >= )
{
result[index] = nSum + '';
nTake = ;
}
else
{
nSum = + nSum;
result[index] = nSum + '';
nTake = -;
}
--n_index;
--m_index;
++index;
} if (nTake == ) result[index++] = nTake + '';
else if (nTake == -) result[index++] = '-'; if (isResetPosNeg) result[index++] = '-';
else if (n_signed == - && m_signed == -) result[index++] = '-'; result[index] = '\0';
} // 从后往前打印出这个数字,并忽略开头的0
void PrintNumber(char* number)
{
bool isBeginning0 = true;
int length = strlen(number); for (int i = length - ; i >= ; --i)
{
if (i == length - && number[i] == '-')
{
printf("%c", '-');
continue;
} if (isBeginning0 && number[i] != '')
{
isBeginning0 = false;
} if (!isBeginning0)
{
printf("%c", number[i]);
}
else
{
if (i == ) printf("%c", '');
}
}
} int main(void)
{
#ifdef Joshua_OJ
freopen("in.txt", "r", stdin);
#endif
int num;
char n[];
char m[];
char result[]; scanf("%d", &num);
while (num--)
{
scanf("%s %s", n, m);
BigNumberAdd(n, m, result);
if (gInvalid)
{
printf("%s\n", "invalid number");
continue;
}
PrintNumber(result);
printf("\n");
} #ifdef Joshua_OJ
fclose(stdin);
#endif return ;
}

输入第一个数表示有多少组数据,对于无效数据需要输出invalid number

Input:

15
200 -22
22 -200
-200 22
-22 200
0 0
000 000
-111 -111
-50 50
50 -50
-333 -333
222 -100
222.222 222
123222222222456 89701234562222222
11111111111111111 11111111111111100
9999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999

Output:

178
-178
-178
178
0
0
-222
0
0
-666
122
invalid number
89824456784444678
22222222222222211
19999999999999999999999999999999999999999999999999999998

C++实现两个大整数的相加(考虑到负数异常情况)的更多相关文章

  1. 华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)

    题目描述: 输出两个不超过100位的大整数的乘积. 输入: 输入两个大整数,如1234567 123 输出: 输出乘积,如:151851741 样例输入: 1234567 123 样例输出: 1518 ...

  2. C++ string 实现大整数相加减

    随意两个大整数的加减算法.可自己主动推断正负号.代码例如以下: #include <iostream> #include <vector> #include <cstri ...

  3. Javascript实现大整数加法

    记得之前面试还被问到过用两个字符串实现两个大整数相加,当时还特别好奇好好的整数相加,为什么要用字符串去执行.哈哈,感觉当时自己还是很无知的,面试官肯定特别的无奈.今天在刷算法的时候,无意中看到了为什么 ...

  4. ACM学习之路————一个大整数与一个小整数不得不说得的秘密

    这个相对于两个大整数的运算来说,只能说是,low爆了. 只要利用好除法的性质,这类题便迎刃而解.O(∩_∩)O哈哈~ //大整数除一个int数 #include<iostream> #in ...

  5. 大整数算法[11] Karatsuba乘法

    ★ 引子         前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) ...

  6. 大整数乘法python3实现

    因为python具有无限精度的int类型,所以用python实现大整数乘法是没意义的,可是思想是一样的.利用的规律是:第一个数的第i位和第二个数大第j位相乘,一定累加到结果的第i+j位上,这里是从0位 ...

  7. [转]大整数算法[11] Karatsuba乘法

    ★ 引子         前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) ...

  8. 算法笔记_034:大整数乘法(Java)

    目录 1 问题描述 2 解决方案 2.1 蛮力法   1 问题描述 计算两个大整数相乘的结果. 2 解决方案 2.1 蛮力法 package com.liuzhen.chapter5; import ...

  9. Coefficient Computation (大整数、Java解决)

    Coefficient Computation UVALive8265 题意:计算组合数C(n,k)的值并将值按给定的进制输出. 思路:Java大整数类硬上. PS:刚刚学完Java的大整数类,结果却 ...

随机推荐

  1. 微信小程序开发调试技巧

    1.  查看线上小程序console a.  先打开开发小程序console b.  再打开线上小程序,此时可以查看console

  2. linux cat显示若干行

    [一]从第3000行开始,显示1000行.即显示3000~3999行 cat filename | tail -n +3000 | head -n 1000 [二]显示1000行到3000行 cat ...

  3. Thunder-Beta发布-事后诸葛亮会议-2017秋-软件工程第十一次作业

    小组名称:Thunder项目名称:爱阅APP小组成员:王航 李传康 翟宇豪 邹双黛 苗威 宋雨 胡佑蓉 杨梓瑞一.设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有 ...

  4. mysql hibernate 关于默认值

    字段的默认值 写 NOT NULL DEFAULT 0 等等 一直不行, 算了  干脆在创建的时候 在代码set好了 版权声明:本文为博主原创文章,未经博主允许不得转载.

  5. 牛客网国庆集训派对Day3题目 2018年

    链接:https://www.nowcoder.com/acm/contest/203/D来源:牛客网 Shopping 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K ...

  6. lintcode-513-完美平方

    513-完美平方 给一个正整数 n, 找到若干个完全平方数(比如1, 4, 9, ... )使得他们的和等于 n.你需要让平方数的个数最少. 样例 给出 n = 12, 返回 3 因为 12 = 4 ...

  7. angularJS1笔记-(19)-angular异步加载包的方式

    我们平时写的导入包的方式都是同步方式,有时候会显得过于卡顿,这样我们就可以使用异步加载的方式. script.js方式: 执行结果为: 异步加载还可以加载多个即为script([,,,],functi ...

  8. js中的let\var\const

    在JavaScript中有三种声明变量的方式:var.let.const.下文给大家介绍js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始 ...

  9. 深入理解JAVA集合系列二:ConcurrentHashMap源码解读

    HashMap和Hashtable的区别 在正式开始这篇文章的主题之前,我们先来比较下HashMap和Hashtable之间的差异点: 1.Hashtable是线程安全的,它对外提供的所有方法都是都使 ...

  10. File FileStream StreamReader StreamWriter C#

    存在各种各样的IO设备,比如说文件File类(字符串文件和二进制文件),可以直接使用File类对文件进行读写操作. 这些各种IO的读取和写入是通过流的形式实现的,基类为Stream,针对各种不同的IO ...