• 【模板小程序】十进制大数相加(正整数版本+整数版本【正负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

    『注:本文来自博客园“小溪的博客”,若非声明均为原创内容,请勿用于商业用途,转载请注明出处http://www.cnblogs.com/xiaoxi666/』
  • 相关阅读:
    用mysql+redis实现微博feed架构上需要注意哪些问题
    windows7下安装zend studio5.5
    鼠标移出DIV层时,触发onMouseOut事件
    关于MVVM和RAC的一些拓展阅读
    Swift(上) 常量, 变量, 数据类型, 循环, 选择结构 简单函数
    SDWebImage的使用
    App Store新应用提审攻略
    关于iOS的推送服务的点点
    iOS开发代码规范
    伟大的RAC和MVVM入门(二)
  • 原文地址:https://www.cnblogs.com/xiaoxi666/p/7258312.html
Copyright © 2020-2023  润新知