1. 程式人生 > >高精度 加 減 乘 除(C++實現)

高精度 加 減 乘 除(C++實現)

如果輸入資料是long long 一下的話, 用這些勉強算是高精度的演算法會比較快

//這是該大數演算法的必須構造的陣列形式

s[1] = a;
    while(s[len] >= 10){
        s[len + 1] += s[len] / 10;
        s[len] %= 10;
        ++len;
   }

乘法(可以算輸入資料為long long時的大數相乘)

#include <iostream>

using namespace std;

typedef long long ll;

ll s[1000]; // 儲存結果
ll len = 1;

void multi(ll x){
    for(int i = 1; i <= len; ++i){
        s[i] *= x;
    }
    for(int i = 1; i <= len; ++i){
        if(s[i] >= 10){
            s[i + 1] += s[i] / 10;
            s[i] %= 10;
        }
    }
    // 如果最高位有進位的話長度加一
    ++len;
    // 去掉最高位面前的0 如0123 0就可以不要
    while(s[len] == 0) --len;
}

void solve(){
    ll a, b;
    cin >> a >> b;
    // 先處理一下資料,讓高位聚集在陣列尾部,便於之後的處理
    s[1] = a;
    while(s[len] >= 10){
        s[len + 1] += s[len] / 10;
        s[len] %= 10;
        ++len;
   }
   multi(b);
   for(int i = len; i >= 1; --i){
        cout << s[i];
   }
}

int main(){
    solve();
    return 0;
}

除法(可以算輸入資料為long long時的大數相除, 被除數可以是大數)

#include <iostream>

using namespace std;

typedef long long ll;
ll s[1000]; // 儲存結果
ll len = 1;

void divis(ll b){
    // 除以單個數 如果不夠除讓高位數和低位相加
    for(int i = len; i >= 1; --i){
        s[i - 1] += (s[i] % b) * 10;
        s[i] /= b;
    }
    while(s[len] == 0) --len;
}

void solve(){
    ll a, b;
    cin >> a >> b;
    s[1] = a;
    // 讓高位資料聚集在尾部
    while(s[len] >= 10){
        s[len + 1] += s[len] / 10;
        s[len] %= 10;
        ++len;
    }
    divis(b);
    if(len <= 0) cout << 0;
    else{
        for(int i = len; i >= 1; --i) cout << s[i];
    }
}

int main(){
    solve();
    return 0;
}

加法(可以算輸入資料為long long時的大數相除, 被加數可以是大數,減數可以用大數表示,這樣就可以進行更高精度的運算了)

#include <iostream>

using namespace std;

typedef long long ll;
ll s[10000];
int len = 1;

void add(ll b){
    int i = 1;
    // b % 10 先取出個位數 跟個位數相加
    // b也可以用陣列儲存,這樣數字就不在侷限於long long 了
    while(b){
        s[i] += b % 10;
        b /= 10;
        ++i;
    }
    len = max(len, i);
    for(int i = 1; i <= len; ++i){
        if(s[i] >= 10){
            s[i + 1] += s[i] / 10;
            s[i] %= 10;
        }
    }
    ++len; // 如果最高位有進位的話,長度加一
    while(s[len] == 0) --len;
}

void solve(){
    ll a, b;
    cin >> a >> b;
    // 讓高位的資料聚集在尾部
    s[1] = a;
    while(s[len] >= 10){
        s[len + 1] += s[len] / 10;
        s[len] %= 10;
        ++len;
    }
    add(b);
    if(len > 0)
        for(int i = len; i >= 1; --i) cout << s[i];
    else cout << 0;
}

int main(){
    solve();
    return 0;
}

減法(可以算輸入資料為long long時的大數相除, 被減數可以是大數,加數可以用大數表示,這樣就可以進行更高精度的運算了)

#include <iostream>

using namespace std;

typedef long long ll;

int s[1000];
int len = 1;

void sub(ll a){
    int i = 1;
    // 這個 a取出個位數是可以用 像是儲存大數資料的s[len] 來表示的 這是跟加法相似的
    while(a){
        s[i] -= a % 10;
        a /= 10;
        ++i;
    }
    len = max(len, i);
    for(int i = 1; i <= len; ++i){
        if(s[i] < 0){
            // 如果小於0, 要向高位取1, 高位就要減一
            s[i] += 10;
            --s[i + 1];
        }
    }
    while(s[len] == 0) --len;
}

void solve(){
    ll a, b;
    cin >> a >> b;
    // 讓高位的資料聚集在尾部
    s[1] = a;
    while(s[len] >= 10){
        s[len + 1] += s[len] / 10;
        s[len] %= 10;
        ++len;
    }
    sub(b);
    for(int i = len; i >= 1; --i){
        cout << s[i];
    }
}

int main(){
    solve();
    return 0;
}
更高精度的運算速度是會降低的,但是如果資料不是特別大的話,這些已經夠用了。後面更高精度的運算,下篇部落格再寫吧!