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的大整数类,结果却 ...
随机推荐
- oozie-ext
安装oozie的时候需要ext的包支持,网站上找了一遍不是没有就是这个csdn下载还需要币,麻蛋...下面给出这个链接,在百度云上,如果失效了,在评论区或者给我留言,再发,一下是ext2.2.zip ...
- find 删除文件
find 目录 -type f -name '*' -print0 | xargs -0 rm
- js中使用对象注意
var myObject = { hello: '你好', world : '世界' } 正常使用 myObject.hello //输出你好 若引用的属性本身是一个变量: 需要用方括号使用 va ...
- C++ 类的定义与实现
摘自这篇博客https://blog.csdn.net/xulingxin/article/details/81335030 一."类" 的介绍 在C++中, 用 &q ...
- Scrum Meeting 11.07
成员 今日任务 明日计划 用时 徐越 赵庶宏 薄霖 卞忠昊 JOSN数据解析 WebView和JavaScript交互基础 3h 武鑫 设计界面:独立完成一些简 ...
- 线程局部存储TLS(thread local storage)
同一全局变量或者静态变量每个线程访问的是同一变量,多个线程同时访存同一全局变量或者静态变量时会导致冲突,尤其是多个线程同时需要修改这一变量时,通过TLS机制,为每一个使用该全局变量的线程都提供一个变量 ...
- 单片机FLASH与RAM、ROM的关系
片机FLASH主要用作程序存贮器,就是替代以前的ROM,最大的有有点是降低了芯片的成本并且可以做到电擦写,目前市场上单片机的FALSH寿命相差比较大,擦写次数从1000~10万的都有,但存储时间可以保 ...
- 6/5 sprint2 看板和燃尽图的更新
- Alpha阶段敏捷冲刺⑤
1.提供当天站立式会议照片一张. 每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 新增了一个登录界面 完成记账的分类模块 报表界面初步设计 今天要完成 ...
- Apache优化之多路处理模块理解
前言: 当项目被多人访问时导致访问数度变慢,查了许多资料,了解到Apache的核心模块——MPM(多路处理访问模块).在此对MPM的一些知识点进行整理. MPM_WINNT模块 windows系统使用 ...