码迷,mamicode.com
首页 > 其他好文 > 详细

高精度问题之大数相加(原来就是用字符串相加,模拟手算这么简单!)

时间:2015-07-28 23:03:16      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

解题心的: 就是基本的一对一模拟手算。。借助c++的string 不用逆序运算了。很方便的补0.  最后处理下前导0的问题。

#include <iostream>
#include <string>
using namespace std;

// 实现大数相加  结果存放在num中 

void bigIntergerAdd(string &num, string add) {
    
    int goBit = 0; // 存放进位
    
    // 先交换下顺序  加数的位数要比较少
    if (num.length() < add.length()) {
    
        string tmp = num;
        num = add;
        add = tmp;
    } 
    
    string tmp (num.length() - add.length(), 0);
    add = tmp + add; 
    
    // 利用string的+号特性  不采用逆序相加法 
    int len1 = num.length(), len2 = add.length();
    for (int i = len1 -1 ; i>= 0; --i) {
        
        int tmp =  ((num[i] - 0) + (add[i] - 0) + goBit) ;
        
        num[i] = tmp% 10 + 0;
        
        goBit = tmp/10;
    }

    // 特殊情况处理
    if (goBit != 0) 
        num.insert(0, string(1, (char)goBit +0)); 
} 


int main(int argc, char** argv) {

    string s1;
    string result;
    int i =0;
    while (cin>> s1) {
    
        if (s1 == "0") {
            
            cout<< result<< endl;
            break;
        } 
        
        if (i ==0) {
            
            i=1;
            result = s1;
        } else 
            bigIntergerAdd(result, s1);
        
        
    } 
    return 0;
}

参考:http://blog.csdn.net/wu5151/article/details/47100085

----------------------------------------------------------------------------------

大数相乘:总的思路比较简单, 就是模拟手算。 用较短(或相等)长度的数的每一位与较长数一一相乘。要注意的是,相乘所得结果需要补0的细节 。然后就是单纯的大数相加。

#include <iostream>
#include <string>
using namespace std; 

// 大数相乘 

string bigIntegerPlus(string res, string plusN) {
    
    string ret; 
    if (res.length()< plusN.length()) {
        
        string tmp = res;
        res = plusN;
        plusN = tmp; 
    }
    
    int len1 = res.length(), len2 = plusN.length();
    for (int i = len2-1; i>=0; --i ) {
        
        string tmp(len1, 0); // 存放相乘的中间结果 
        int goBit =0;
        for (int j= len1-1; j >=0; --j) {
        
            int mid = (res[j] -0) * (plusN[i] -0) + goBit;
            tmp[j] = mid%10 + 0;
            goBit = mid /10;
        }
        if (goBit != 0) 
            tmp.insert(0, string(1,goBit +0));
        
        for (int m=0; m< len2 -1-i; ++m)
            tmp.push_back(0); // 补位  
        
        // 相乘后就相加  大数相加
        if (i == len2-1)
            ret = tmp;
        else {
            
            int goBit2 =0; 
            string s(tmp.length() - ret.length() ,0);
            ret = s + ret;
            for (int m = tmp.length()-1; m>=0; --m) {
                
                int mid = (tmp[m] -0)+(ret[m] - 0)  + goBit2;
                ret[m] = mid %10 +0;
                goBit2 = mid/ 10;    
            }
            
            if (goBit2 != 0) 
                ret.insert(0, string(1,goBit +0));
        }     
    } 

    // 去掉前导0
    while (ret.length() >1 && ret[0] == 0)
        ret.erase(0,1);
     
    return ret;    
}


int main(int argc, char** argv) {
    
    string res, plusN;
    while (cin>> res>> plusN) {
        
        cout<< bigIntegerPlus(res, plusN)<< endl;
    }
    
    return 0;
}

参考:http://blog.csdn.net/wu5151/article/details/47099971

----------------------------------------------------------------------------------

实现的是大数跟int类型的相除和求余,解题心得: 模拟手算的过程。需要注意的是。其中余数的存放要用long long存放比较好。因为如果采用int类型那么     rem = prem * 10/*向后退一位*/ + src[i] - ‘0‘;    这行代码可能会出现溢出问题。

#include <iostream>
#include <cstring>
using namespace std;

void bigDivision(char *src, int num, char sign) {
    
    long long rem = 0; // 存放新余数 
    long long prem = 0; // 原余数
    char  res[10000] ="";
    bool flag = true;
    int k = 0;
    for (int i=0; i< strlen(src); ++i) {
        
        rem = prem * 10/*向后退一位*/ + src[i] - 0;
        if (rem / num >0 || rem ==0) {
            
            res[k++] = rem/ num + 0;
            prem = rem %num;
            flag = false;
        }  else {
            
            prem = rem;
            if (!flag)
                res[k++] = 0;
        }
    }
    if (sign == %) {
        
        cout<< prem<< endl;
        return;
    }
    
    for (int i =0; i< k; ++i) 
        cout<< res[i];
    cout<< endl;
} 

int main(int argc, char** argv) {
    
    char src[10000] = "";
    int num;
    char sign;
    while (scanf("%s %c %d", src, &sign, &num) != EOF) {
        
        bigDivision(src, num, sign);
    }
    
    return 0;
}

参考:http://blog.csdn.net/wu5151/article/details/47100165

----------------------------------------------------------------------------------

高精度问题之大数求幂,解题思路: 因为做了大数相加 ,这题也就没什么好思考的。不同之处就是先去掉小数点,计算结果后在适当位置插入小数点即可。这个算法可以计算更大的数。但必须包含小数点。。。。。。

#include <iostream>
#include <string>
using namespace std;

// 求幂  思路: 先变成整数相乘   然后根据小数的位数 结合幂  算出小数点该结果字符串的位置 即可

string bigIntegerPlus(string src, string num) {
    
    string tmp = src;
    for (int i =num.length() -1; i >= 0 ; --i) {
        
        string mid(tmp.length(),0);
        int goBit =0;
        for (int j =  tmp.length()-1; j >= 0; --j) {
            
            int tm = goBit + (tmp[j] -0)* (num[i] - 0);
            mid[j] = tm% 10 +0;
            goBit = tm  /10;
        }
        
        for (int q = num.length()-1; q> i; --q) 
            mid.push_back(0);
        if (goBit != 0) 
            mid.insert(0, string(1, (char)goBit +0));

        // 加法运算
        if (i == num.length()-1)
            src = mid;
        else {
        
            goBit =0;
            string s(mid.length() - src.length(), 0);
            src = s + src;
            for (int j = mid.length()-1; j>=0; --j) {
            
                int tm = (mid[j] - 0) +(src[j] - 0) + goBit;
                src[j] = tm %10 + 0;
                goBit = tm /10;
            }

            if (goBit !=0) 
                src.insert(0, string(1, (char)goBit +0));
        }    
    }
    return src;
}

int main(int argc, char** argv) {
    
    string str;
    while ( getline(cin, str)) {
        
        // 分割出待积数 和 幂  以及小数点位置
        int i =0;
        int index = 0;// 小数位置
        int count = 0;//幂次数
        string num;
        while ( i< str.length()) {
            
            if ( str[i] !=  ) {
            
                if (str[i] == .)
                    index = i;
                else
                    num.push_back(str[i]);
                ++i;
                continue;
            }
            while ( !isdigit(str[i])) 
                ++i;
            
            if (i + 1 == str.length())
                count = str[i] - 0;
            else 
                count = (str[i] - 0) * 10 + str[i+1] - 0;        
            break;        
        }
        
        index = num.length() - index;
            
        string res = num;
        for (int i =0; i< count-1; ++i) {
        
            res = bigIntegerPlus( res, num);
        }
        index = index * count;
        
        res.insert(res.length() - index, string(".")); 
        
        while (res.length() >1 && res[0] == 0)
            res.erase(0, 1);
        
        for (int i =res.length()-1; i>=0; --i) {
            
            if (res[i] == 0 )
                res.erase(i, i+1);
            else 
                break;
        }
        cout<< res<< endl;    
    }
    
    return 0;
}

参考:http://blog.csdn.net/wu5151/article/details/47100327

高精度问题之大数相加(原来就是用字符串相加,模拟手算这么简单!)

标签:

原文地址:http://www.cnblogs.com/findumars/p/4684361.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!