阿鲲的博客 主修软件工程和算法模型,极客成长中

oj-大数的四则运算

2019-03-01
jktian

阅读:


知识点

  1. 文本文件是字符均为ascii编码的文件;其余为二进制文件
  2. 注意’0’在char和int之间的作用
  3. 第一步。对输入的数据标准化,明确每个数据/变量的含义、类型,增强代码的可解释性
  4. 测试用例的挑选。选最小的规模的能体现问题所在的用例。一旦出现问题,马上进行分析更改,脑中运行后,再开始run, 节省机器运行时间
  5. 解决问题的思路:搭建步骤框架,解决最小子问题(构建积木),然后搭积木(建大厦)。
    1. 单元测试和集成测试必不可少

加法

    #include<iostream>
    #include<cmath>
    #include<string>
    #include<iterator>
    #include<algorithm>

    using namespace std;
    
    // big num add
    string bigNumAdd(string num1,string num2){
        // reverse
        reverse(num1.begin(),num1.end());
        reverse(num2.begin(),num2.end());

        // standard-process data
        string bignum,smallnum,sumnum;
        if(num1.size()>num2.size()){
            bignum = num1; smallnum = num2;
        }else{
            bignum = num2; smallnum = num1;
        }
        sumnum = bignum;

        // add
        for(int i=0;i<smallnum.size();i++){
            int lowposVal = smallnum[i]-'0'+sumnum[i]-'0';
            int lowpos = i;
            sumnum[lowpos] = lowposVal+'0';
            while(lowposVal>9){
                sumnum[lowpos] = lowposVal+'0'-10;
                if(lowpos+1>=sumnum.size()){
                    sumnum.append(1,'0');
                }
                sumnum[lowpos+1] += 1;
                lowposVal = sumnum[lowpos+1]-'0';
                lowpos += 1;
            }

        }

        // return
        reverse(sumnum.begin(),sumnum.end());
        cout <<  sumnum << endl;
        return sumnum;
    }

    int main(){
        string num1,num2,sumnum;
        cin >> num1 >> num2;
        sumnum = bigNumAdd(num1,num2);
        return 0;
    }

减法

  1. 在加法的基础上改动,增加了符号判断函数

     char cmpStr(string num1,string num2){
         char sign = '+';
         // 1.size; 2. equation
        if(num1.size()>num2.size()){
            sign = '+';
        }else if(num1.size()<num2.size()){
            sign = '-';
        }else{
            for(int i=0;i<num1.size();i++){
                if(num1[i]>num2[i]){
                    sign = '+';  break;
                }else if(num1[i]<num2[i]){
                    sign = '-';  break;
                }else{}
            }
        }
        return sign;
     }
     // big num sub
     string bigNumSub(string num1,string num2){
         // get-sign
         char sign = cmpStr(num1,num2);
        
         // reverse
         reverse(num1.begin(),num1.end());
         reverse(num2.begin(),num2.end());
        
         // standard-process data
         string bignum,smallnum,sumnum;
         if(sign=='+'){
             bignum = num1; smallnum = num2;
         }else{
             bignum = num2; smallnum = num1;
         }
         sumnum = bignum;
        
         // sub
         for(int i=0;i<smallnum.size();i++){
             int lowposVal = sumnum[i]-smallnum[i];
             int lowpos = i;
             sumnum[lowpos] = lowposVal+'0';
             while(lowposVal<0){
                 sumnum[lowpos] = 10+lowposVal+'0';
     //            if(lowpos+1>=sumnum.size()){
     //                sumnum.append(1,'0');
     //            }
                 sumnum[lowpos+1] -= 1;
                 lowposVal = sumnum[lowpos+1]-'0';
                 lowpos += 1;
             }
        
         }
        
         // return
         reverse(sumnum.begin(),sumnum.end());
         cout <<  sign << sumnum << endl;
         return sumnum;
     }
    

乘法

  1. 先写出函数,实现大数与一位整数相乘

    #include #include #include #include #include #include "bignumadd.h" using namespace std; string mulOnepos(string bignum, char smallOne){ string res; int curNum=0, lowNum=0, highNum=0;

    // reverse(bignum.begin(),bignum.end());

     for(int i=0;i<bignum.size();i++){
         curNum = highNum + (bignum[i]-'0')*(smallOne-'0');
         lowNum = curNum % 10;
         if(curNum>=10){
             highNum = curNum / 10;
         }else{
             highNum = 0;
         }
         res.append(1,lowNum+'0');
     }
     if(highNum!=0){
         res.append(1,highNum+'0');
     }
     reverse(res.begin(),res.end());
     return res;  }
    

    // big num multiply string bigNumMul(string num1,string num2){ // reverse reverse(num1.begin(),num1.end()); reverse(num2.begin(),num2.end());

     // standard-process data
     string bignum,smallnum,sumnum;
     if(num1.size()>num2.size()){
         bignum = num1; smallnum = num2;
     }else{
         bignum = num2; smallnum = num1;
     }
        
     // multiply
     for(int i=0;i<smallnum.size();i++){
         string tmp = mulOnepos(bignum, smallnum[i]);
         tmp.append(i,'0');  //        cout << i << " : tmp after o-add: " << tmp << endl;
         sumnum = bigNumAdd(tmp,sumnum);  //        cout << i << " : sumnum " << sumnum << endl;
     }
    

    // reverse(sumnum.begin(),sumnum.end()); cout «  sumnum « endl; return sumnum; }

    int main(){ string num1,num2,sumnum; cin » num1 » num2; sumnum = bigNumMul(num1,num2); // cout « mulOnepos(num1,num2[0]) « endl; return 0; }

除法

  1. 基于减法操作
  2. 符号判断时,要加入为0的判断。同时,要去除前缀的冗余0

    string rmDupZero(string num1){ int len = num1.size(),i; for(i=0;i<len;i++){ if(num1[i]!=’0’){ break; } } num1 = num1.substr(i,len-i); return num1; } char cmpStr(string num1,string num2){ char sign = ‘+’; // remove duplicate-zero num1 = rmDupZero(num1); num2 = rmDupZero(num2);

    // 1.size; 2. equation
    if(num1.size()>num2.size()){
        sign = '+';
    }else if(num1.size()<num2.size()){
        sign = '-';
    }else{
        for(int i=0;i<num1.size();i++){
            if(num1[i]>num2[i]){
                sign = '+';  break;
            }else if(num1[i]<num2[i]){
                sign = '-';  break;
            }else{
                sign = '=';
            }
        }
    }
    return sign;  }  // big num sub  string bigNumSub(string num1,string num2){
     // get-sign
     char sign = cmpStr(num1,num2);
    
     // reverse
     reverse(num1.begin(),num1.end());
     reverse(num2.begin(),num2.end());
    
     // standard-process data
     string bignum,smallnum,sumnum;
     if(sign=='+'){
         bignum = num1; smallnum = num2;
     }else{
         bignum = num2; smallnum = num1;
     }
     sumnum = bignum;
    
     // sub
     for(int i=0;i<smallnum.size();i++){
         int lowposVal = sumnum[i]-smallnum[i];
         int lowpos = i;
         sumnum[lowpos] = lowposVal+'0';
         while(lowposVal<0){
             sumnum[lowpos] = 10+lowposVal+'0';  //            if(lowpos+1>=sumnum.size()){  //                sumnum.append(1,'0');  //            }
             sumnum[lowpos+1] -= 1;
             lowposVal = sumnum[lowpos+1]-'0';
             lowpos += 1;
         }
    
     }
    
     // return
     reverse(sumnum.begin(),sumnum.end());  //    cout <<  sign << sumnum << endl;
     return sign+sumnum;  }
    

    string bigNumDiv(string num1, string num2){ if(num2[0]==’0’){ string hint = “zero-error”; return hint; } string res,tmp; string num1Copy = num1, num2Copy = num2; int len1 = num1.size(); int len2 = num2.size(); int dlen = len1 - len2; for(int i=0;i<=dlen;i++){ res.append(1,’0’); num2.append(dlen-i,’0’); tmp = bigNumSub(num1,num2); while(tmp[0]==’+’){ res[i] += 1; num1 = tmp.substr(1,tmp.size()-1);

             cout << "num1(after-sub): num2(division) = " << num1 << " , " << num2<< endl;
             cout << "res: " << res << endl;
             tmp = bigNumSub(num1,num2);
             cout << "tmp(next-try): " << tmp << endl;
             cout << "******************" << endl;
         }
         num2 = num2Copy;
     }
     if(tmp[0]=='='){
         res[res.size()-1] += 1;
     }
     cout << res << endl;
     return res;  }
    

Similar Posts

Comments