高精度問題之大數相加(原來就是用字符串相加,模擬手算這么簡單!)


解題心的: 就是基本的一對一模擬手算。。借助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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM