【模板小程序】十进制大数相加(正整数版本+整数版本【正负0】),包含合法性检查

为适应于不同用途,将大数算法写成了两个版本,分别为只处理正整数的版本和包含负数处理的版本,可根据需要选用。

版本1:只能处理正整数

 1 //大数相加(十进制正整数),用string处理
 2 #include <iostream>
 3 #include <string>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 //输入数据合法性检查,数字必须在0-9范围内
 9 bool IsVaild(const string& num1,const string& num2)
10 {
11     for(auto val:num1)
12     {
13         if(!(val>='0' && val-'0'<='9'))
14             return false;
15     }
16     for(auto val:num2)
17     {
18         if(!(val>='0' && val<='9'))
19             return false;
20     }
21     return true;
22 }
23 
24 string greatNumberAdd(string num1,string num2)
25 {
26     const size_t len1=num1.length();
27     const size_t len2=num2.length();
28     const size_t n=len1>len2 ? len1 :len2;
29     reverse(num1.begin(),num1.end());
30     reverse(num2.begin(),num2.end());
31     
32     string result;
33     int carry=0;
34     for(size_t i=0;i<n;++i)
35     {
36         const int num1i = i<len1 ? num1[i]-'0' :0;
37         const int num2i = i<len2 ? num2[i]-'0' :0;
38         const int val   = (num1i+num2i+carry)%10;
39         carry=(num1i+num2i+carry)/10;
40         result.insert(result.begin(),val+'0');
41     }
42     if(1==carry)//若最前面有进位,则插入'1'
43         result.insert(result.begin(),'1');
44     
45     return result;
46 }
47 
48 int main()
49 {
50     string num1,num2;
51     while(cin>>num1>>num2)
52     {
53         if(IsVaild(num1,num2))
54             cout<<greatNumberAdd(num1,num2)<<endl;
55         else
56             cout<<"输入数据不合法"<<endl;
57     }
58     return 0;
59 }

 

版本2:可处理正整数、0、负整数(STL编码风格)

  1 /*
  2 本程序说明:
  3 
  4 大数相加(十进制正负整数),用string处理
  5 
  6 时间复杂度:O(k),k为字符串长度(取大者)
  7 空间复杂度:O(1)
  8 
  9 */
 10 
 11 #include <iostream>
 12 #include <string>
 13 #include <algorithm>
 14 
 15 using namespace std;
 16 
 17 //输入数据合法性检查,数字必须在0-9范围内
 18 bool IsVaild(const string& num1,const string& num2)
 19 {
 20     for(size_t i=0;i<num1.length();++i)
 21     {
 22         if(0==i && '-'==num1[0] && ++i<num1.length()){};//首位可以是'-',这里直接加i,继续判断
 23         if(!(num1[i]>='0' && num1[i]-'0'<='9'))
 24             return false;
 25     }
 26     for(size_t i=0;i<num2.length();++i)
 27     {
 28         if(0==i && '-'==num2[0] && ++i<num2.length()){};//首位可以是'-',这里直接加i,继续判断
 29         if(!(num2[i]>='0' && num2[i]-'0'<='9'))
 30             return false;
 31     }
 32     return true;
 33 }
 34 
 35 //辅助函数:num1-num2
 36 string __greatNumberMinu(string num1,string num2)
 37 {
 38     const size_t len1=num1.length();
 39     const size_t len2=num2.length();
 40     const size_t n=len1>len2 ? len1 :len2;
 41     reverse(num1.begin(),num1.end());
 42     reverse(num2.begin(),num2.end());
 43 
 44     string result;
 45     int carry=0;//借位
 46     for(size_t i=0;i<n;++i)
 47     {
 48         const int num1i = i<len1 ? num1[i]-'0' :0;
 49         const int num2i = i<len2 ? num2[i]-'0' :0;
 50         const int val   = (num1i-carry-num2i>=0) ? (num1i-carry-num2i) : (num1i-carry-num2i+10);
 51         carry=(num1i-carry-num2i>=0) ? 0 : 1;
 52         result.insert(result.begin(),val+'0');
 53     }
 54     int firstIndex_notEqualTo_0=0;//找出第一个不为0的位置(如果前面均为0,则抹去)
 55     for(;firstIndex_notEqualTo_0<result.length();++firstIndex_notEqualTo_0)
 56     {
 57         if(result[firstIndex_notEqualTo_0]!='0')
 58             break;
 59     }
 60     if(firstIndex_notEqualTo_0>0)//(如果前面均为0,则抹去)
 61         result.erase(0,firstIndex_notEqualTo_0);
 62 
 63     return result;
 64 }
 65 
 66 //辅助函数:符号为一正一负时调用,这里的num1和num2不包含符号位(较大的减较小的,在本函数内判断),sign为判断位
 67 string _greatNumberMinu(string num1,string num2,bool flag)
 68 {
 69     string result;
 70 
 71     size_t len1=num1.length();
 72     size_t len2=num2.length();
 73     if(len1>len2)//字符串比较,必须先判断长度(不能直接比较字符串,例如比较结果"2">"111",实际上按照数值来看"111">"2")
 74     {
 75         result=__greatNumberMinu(num1,num2);
 76         if(flag)
 77             result.insert(result.begin(),'-');//在最前面添加'-'
 78     }
 79     else if(len1<len2)
 80     {
 81         result=__greatNumberMinu(num2,num1);
 82         if(!flag)
 83             result.insert(result.begin(),'-');//在最前面添加'-'
 84     }
 85     else/*len1==len2*/
 86     {
 87         if(num1>num2)//字符串比较(两字符串长度相等时就可以比较了)
 88         {
 89             result=__greatNumberMinu(num1,num2);
 90             if(flag)
 91                 result.insert(result.begin(),'-');//在最前面添加'-'
 92         }
 93         else if(num1<num2)
 94         {
 95             result=__greatNumberMinu(num2,num1);
 96             if(!flag)
 97                 result.insert(result.begin(),'-');//在最前面添加'-'
 98         }
 99         else
100             result="0";
101     }
102 
103     return result;
104 }
105 
106 //辅助函数:符号为两正和两负时调用,这里的num1和num2不包含符号位
107 string _greatNumberAdd(string num1,string num2)
108 {
109     const size_t len1=num1.length();
110     const size_t len2=num2.length();
111     const size_t n=len1>len2 ? len1 :len2;
112     reverse(num1.begin(),num1.end());
113     reverse(num2.begin(),num2.end());
114 
115     string result;
116     int carry=0;//进位
117     for(size_t i=0;i<n;++i)
118     {
119         const int num1i = i<len1 ? num1[i]-'0' :0;
120         const int num2i = i<len2 ? num2[i]-'0' :0;
121         const int val   = (num1i+num2i+carry)%10;
122         carry=(num1i+num2i+carry)/10;
123         result.insert(result.begin(),val+'0');
124     }
125     if(1==carry)//若最前面有进位,则插入'1'
126         result.insert(result.begin(),'1');
127 
128     return result;
129 }
130 
131 //大数相加入口,先判断符号(两正、两负、一正一负),再调用辅助函数
132 string greatNumberAdd(string num1Andsign,string num2Andsign)
133 {
134     string result;
135     if('-'==num1Andsign[0] && '-'==num2Andsign[0])//两负
136     {
137         result=_greatNumberAdd(num1Andsign.substr(1,num1Andsign.length()-1),num2Andsign.substr(1,num2Andsign.length()-1));
138         result.insert(result.begin(),'-');//在最前面添加'-'
139     }
140     else if('-'==num1Andsign[0] || '-'==num2Andsign[0])//一正一负
141     {
142         if('-'==num1Andsign[0])
143             result=_greatNumberMinu(num1Andsign.substr(1,num1Andsign.length()-1),num2Andsign,true);
144         else if('-'==num2Andsign[0])
145             result=_greatNumberMinu(num1Andsign,num2Andsign.substr(1,num2Andsign.length()-1),false);
146     }
147     else
148         result=_greatNumberAdd(num1Andsign,num2Andsign);//两正
149 
150     int firstIndex_notEqualTo_0=0;//找出第一个不为0的位置(如果前面均为0,则抹去)
151     for(;firstIndex_notEqualTo_0<result.length();++firstIndex_notEqualTo_0)
152     {
153         if(result[firstIndex_notEqualTo_0]!='0')
154             break;
155     }
156     if(firstIndex_notEqualTo_0>0)//(如果前面均为0,则抹去)
157         result.erase(0,firstIndex_notEqualTo_0);
158     if(result.empty())//如果两个数相加结果为0,最后处理完就为空了,因此直接输出"0"
159         result="0";
160     return result;
161 }
162 
163 int main()
164 {
165     string num1,num2;
166     while(cin>>num1>>num2)
167     {
168         if(IsVaild(num1,num2))
169             cout<<greatNumberAdd(num1,num2)<<endl;
170         else
171             cout<<"输入数据不合法"<<endl;
172     }
173     return 0;
174 }

 

为方便理解,特画出版本二的程序运行流程图(为图示清晰,省略了函数形参):

 

 

参考资料来源说明:

1、正整数版本,借鉴了牛客网“赞一下”用户的思想,在此感谢,原题目参见https://www.nowcoder.com/questionTerminal/5821836e0ec140c1aa29510fd05f45fc?orderByHotValue=0&mutiTagIds=578_579&page=2&onlyReference=false

2、含负数版本,参考了这篇文章的实现思路:http://blog.csdn.net/to_be_better/article/details/50375420

 

同类文章:

【模板小程序】 十进制大数相乘(正数、负数、0均可),包含合法性检查:http://www.cnblogs.com/xiaoxi666/p/7272255.html

【模板小程序】 十进制大数除法(不含小数):http://www.cnblogs.com/xiaoxi666/p/7275353.html

posted @ 2017-07-30 09:35  xiaoxi666  阅读(438)  评论(0编辑  收藏  举报
TOP