天天看點

高精度計算(+-*/)(壓位計算)(c++實作)初始化: 加法:減法:乘法: 輸出:完整代碼:

 進來的時候如果沒看見除法,說明我也還不會,會了的話我會補充上去的。如果要看的除法的,得去看别人的了。

目錄

初始化:

 加法:

減法:

乘法:

 輸出:這個是重點!!!!!!!!!!!

完整代碼:

 如果你是從我的“P1601 A+B Problem(高精)”這篇文章來的話,可以看一下壓位計算,更加的快捷友善。

高精度計算就是因為超過了資料表達的類型,從用其他的方式來進行計算。

壓位就是說将一長串的數字分割開來,來單獨進行儲存,進而不會發生超過範圍。

初始化:

可以看到 k 其實就是控制一個int裡面有多少位,你可以自己設定,但如果太大了的話 乘法就有可能越界,如果隻是加減法可以适當的調整大小。

讀入還是得用string類型,沒辦法确實太大了

後面的輸出裡面會說到int類型的一個缺陷。

void Initialization(string str,int num[]){//初始化,用數組的第一位來儲存裡面有幾位
    int n=str.length(),k=1,j=1;
    for(int i=1;i<=n;i++){
        if(k==10000){//表示用的10000進制,也可以自己改進制,但是如果太高的話,乘法和除法不好處理
            j++;
            k=1;
        }
        num[j]+=k*(str[n-i]-'0');
        k=k*10;
    }
    num[0]=j;
    return;
}
           

 加法:

我是建立了一個數組來存放結果,也可以就利用那兩個數組進行運算,但我懶了(其實是不怎麼會,怕出錯)

關鍵點1:就是在于進位,要記得每次都要判斷是否大于10000,我使用10000進制的,如果你改成了其他的,這個數字跟k相同就行

關鍵點2:就是會多一位出來,我代碼裡面也寫了是關鍵,你得判斷多出來的一位裡面有沒有東西,如果有就得加進去。

void addition(int num1[],int num2[]){//加法
    int result[Maxn];
    memset(result,0,sizeof(result));
    result[0]=max(num1[0],num2[0]);
    for(int i=1;i<=result[0];i++){
        result[i]+=num1[i]+num2[i];
        if(result[i]>=10000){//則要進行進位
            result[i]-=10000;
            result[i+1]++;//往前進位
        }
    }
    //下面是關鍵
    if(result[result[0]+1]>0){//類似于9999+1,則會多一位出來,就要判斷是否多了一位。
        result[0]++;
    }
    cout<<result;
}
           

減法:

同樣是建立的數組。

關鍵點1:跟加法不一樣,你得借位,是以是跟0進行比較,并且記得借了一位,要減去

關鍵點2:這裡判斷有沒有多是用 while 循環,跟加法不一樣,他有可能會一直借位,是以得一直判斷。

void subtraction(int num1[],int num2[]){//減法
    int result[Maxn];
    memset(result,0,sizeof(result));
    result[0]=max(num1[0],num2[0]);
    for(int i=1;i<=result[0];i++){
        result[i]+=num1[i]-num2[i];
        if(result[i]<0){//要向前借位
            result[i]+=10000;
            result[i+1]--;
        }
    }
    //下面也是關鍵
    while(result[result[0]]==0&&result[0]>1){//将前面多餘的0删除
        result[0]--;
    }
    cout<<result;
}
           

乘法:

建立。

這個比加法就要難,相當于是多個加法的疊加,而且每次加的時候不是在同一個位置加,會往前跑一個。

進位就不說了。

result[i+j-1]+=num1[i]*num2[j];//減1是為了從第一位開始

這一行代碼如果不能了解的話,可以去列一下豎式,我相信肯定都會明白的,就是往前移一個相加。總不能不會列豎式吧,這要是不會我也沒辦法了 

後面就是判斷前置0的 while 循環了。

void multiplication(int num1[],int num2[]){//乘法
     int result[Maxn];
    memset(result,0,sizeof(result));
    result[0]=num1[0]+num2[0]+1;
    for(int i=1;i<=num1[0];i++){
        for(int j=1;j<=num2[0];j++){//就是豎式算法一樣,一步步來求
            result[i+j-1]+=num1[i]*num2[j];//減1是為了從第一位開始
            result[i+j]+=result[i+j-1]/10000;//進位
            result[i+j-1]%=10000;
        }
    }
    //下面是關鍵
    while(result[result[0]]==0&&result[0]>0){//就是把前面多餘的0删除
        result[0]--;
    }
    cout<<result;
}
           

 輸出:

這次可沒有建立了嗷!

這個輸出其實也可以用其他的方式來輸出,但那樣就得自己去看是不是滿4位了。

我先說為什麼要滿4位輸出

因為int類型裡面存放的時候 “0000” 它是看成 “0”來存放的,比如 10000 放在 int 裡面就會變成

int[1]=0,int[2]=1;這樣輸出的話就會變成10。

是以如果不用流輸出的話,就得自己判斷 int 裡面有幾位,然後要補幾個0,但是用流輸出的話,就可以直接用函數。就很友善,不用自己寫,這還不爽?如果不會流的話,可以去學一下,很快的。

還有就是運算符的重載,學一下也很快的。都是模闆,套一下就好!

ostream&operator<<(ostream &o,int result[]){
    o<<result[result[0]];
    for(int i=result[0]-1;i>0;i--){
        o.width(4);//每次都要輸出4位
        o.fill('0');//如果不夠4位則要補齊,因為int類型裡面的0000會被當作0
        o<<result[i];
    }
    return o;
}
           

完整代碼:

#include<iostream>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<vector>
using namespace std;
const int Maxn=10000;
ostream&operator<<(ostream &o,int result[]){
    o<<result[result[0]];
    for(int i=result[0]-1;i>0;i--){
        o.width(4);//每次都要輸出4位
        o.fill('0');//如果不夠4位則要補齊,因為int類型裡面的0000會被當作0
        o<<result[i];
    }
    return o;
}
void Initialization(string str,int num[]){//初始化,用數組的第一位來儲存裡面有幾位
    int n=str.length(),k=1,j=1;
    for(int i=1;i<=n;i++){
        if(k==10000){//表示用的10000進制,也可以自己改進制,但是如果太高的話,乘法和除法不好處理
            j++;
            k=1;
        }
        num[j]+=k*(str[n-i]-'0');
        k=k*10;
    }
    num[0]=j;
    return;
}
void addition(int num1[],int num2[]){//加法
    int result[Maxn];
    memset(result,0,sizeof(result));
    result[0]=max(num1[0],num2[0]);
    for(int i=1;i<=result[0];i++){
        result[i]+=num1[i]+num2[i];
        if(result[i]>=10000){//則要進行進位
            result[i]-=10000;
            result[i+1]++;//往前進位
        }
    }
    //下面是關鍵
    if(result[result[0]+1]>0){//類似于9999+1,則會多一位出來,就要判斷是否多了一位。
        result[0]++;
    }
    cout<<result;
}
void subtraction(int num1[],int num2[]){//減法
    int result[Maxn];
    memset(result,0,sizeof(result));
    result[0]=max(num1[0],num2[0]);
    for(int i=1;i<=result[0];i++){
        result[i]+=num1[i]-num2[i];
        if(result[i]<0){//要向前借位
            result[i]+=10000;
            result[i+1]--;
        }
    }
    //下面也是關鍵
    while(result[result[0]]==0&&result[0]>1){//将前面多餘的0删除
        result[0]--;
    }
    cout<<result;
}
void multiplication(int num1[],int num2[]){//乘法
     int result[Maxn];
    memset(result,0,sizeof(result));
    result[0]=num1[0]+num2[0]+1;
    for(int i=1;i<=num1[0];i++){
        for(int j=1;j<=num2[0];j++){//就是豎式算法一樣,一步步來求
            result[i+j-1]+=num1[i]*num2[j];//減1是為了從第一位開始
            result[i+j]+=result[i+j-1]/10000;//進位
            result[i+j-1]%=10000;
        }
    }
    //下面是關鍵
    while(result[result[0]]==0&&result[0]>0){//就是把前面多餘的0删除
        result[0]--;
    }
    cout<<result;
}
int main(){
    string str1,str2;
    cin>>str1>>str2;
    int num1[Maxn];
    int num2[Maxn];
    memset(num1,0,sizeof(num1));//将數組裡面的全部值變成0
    memset(num1,0,sizeof(num1));//将數組裡面的全部值變成0
    Initialization(str1,num1);
    Initialization(str2,num2);
    multiplication(num1,num2);
    system("pause");
    return 0;
}
           

繼續閱讀