C++实现两个大整数的相加(考虑到负数异常情况)
实现两个大整数的相加,首先应该排除直接使用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++实现两个大整数的相加(考虑到负数异常情况)的更多相关文章
- 华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)
题目描述: 输出两个不超过100位的大整数的乘积. 输入: 输入两个大整数,如1234567 123 输出: 输出乘积,如:151851741 样例输入: 1234567 123 样例输出: 1518 ...
- C++ string 实现大整数相加减
随意两个大整数的加减算法.可自己主动推断正负号.代码例如以下: #include <iostream> #include <vector> #include <cstri ...
- Javascript实现大整数加法
记得之前面试还被问到过用两个字符串实现两个大整数相加,当时还特别好奇好好的整数相加,为什么要用字符串去执行.哈哈,感觉当时自己还是很无知的,面试官肯定特别的无奈.今天在刷算法的时候,无意中看到了为什么 ...
- ACM学习之路————一个大整数与一个小整数不得不说得的秘密
这个相对于两个大整数的运算来说,只能说是,low爆了. 只要利用好除法的性质,这类题便迎刃而解.O(∩_∩)O哈哈~ //大整数除一个int数 #include<iostream> #in ...
- 大整数算法[11] Karatsuba乘法
★ 引子 前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) ...
- 大整数乘法python3实现
因为python具有无限精度的int类型,所以用python实现大整数乘法是没意义的,可是思想是一样的.利用的规律是:第一个数的第i位和第二个数大第j位相乘,一定累加到结果的第i+j位上,这里是从0位 ...
- [转]大整数算法[11] Karatsuba乘法
★ 引子 前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) ...
- 算法笔记_034:大整数乘法(Java)
目录 1 问题描述 2 解决方案 2.1 蛮力法 1 问题描述 计算两个大整数相乘的结果. 2 解决方案 2.1 蛮力法 package com.liuzhen.chapter5; import ...
- Coefficient Computation (大整数、Java解决)
Coefficient Computation UVALive8265 题意:计算组合数C(n,k)的值并将值按给定的进制输出. 思路:Java大整数类硬上. PS:刚刚学完Java的大整数类,结果却 ...
随机推荐
- 微信小程序开发调试技巧
1. 查看线上小程序console a. 先打开开发小程序console b. 再打开线上小程序,此时可以查看console
- linux cat显示若干行
[一]从第3000行开始,显示1000行.即显示3000~3999行 cat filename | tail -n +3000 | head -n 1000 [二]显示1000行到3000行 cat ...
- Thunder-Beta发布-事后诸葛亮会议-2017秋-软件工程第十一次作业
小组名称:Thunder项目名称:爱阅APP小组成员:王航 李传康 翟宇豪 邹双黛 苗威 宋雨 胡佑蓉 杨梓瑞一.设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有 ...
- mysql hibernate 关于默认值
字段的默认值 写 NOT NULL DEFAULT 0 等等 一直不行, 算了 干脆在创建的时候 在代码set好了 版权声明:本文为博主原创文章,未经博主允许不得转载.
- 牛客网国庆集训派对Day3题目 2018年
链接:https://www.nowcoder.com/acm/contest/203/D来源:牛客网 Shopping 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K ...
- lintcode-513-完美平方
513-完美平方 给一个正整数 n, 找到若干个完全平方数(比如1, 4, 9, ... )使得他们的和等于 n.你需要让平方数的个数最少. 样例 给出 n = 12, 返回 3 因为 12 = 4 ...
- angularJS1笔记-(19)-angular异步加载包的方式
我们平时写的导入包的方式都是同步方式,有时候会显得过于卡顿,这样我们就可以使用异步加载的方式. script.js方式: 执行结果为: 异步加载还可以加载多个即为script([,,,],functi ...
- js中的let\var\const
在JavaScript中有三种声明变量的方式:var.let.const.下文给大家介绍js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始 ...
- 深入理解JAVA集合系列二:ConcurrentHashMap源码解读
HashMap和Hashtable的区别 在正式开始这篇文章的主题之前,我们先来比较下HashMap和Hashtable之间的差异点: 1.Hashtable是线程安全的,它对外提供的所有方法都是都使 ...
- File FileStream StreamReader StreamWriter C#
存在各种各样的IO设备,比如说文件File类(字符串文件和二进制文件),可以直接使用File类对文件进行读写操作. 这些各种IO的读取和写入是通过流的形式实现的,基类为Stream,针对各种不同的IO ...