1. 程式人生 > >大整數運算

大整數運算

相等 %d nbsp multi car 進行 pan 讀取 ring

  大整數存儲

    用一個字符串讀取輸入的大數,在轉換的時候,用反轉的方式存到一個int型的數組中。

    

struct bign{
    int d[1000];
    int len;
    bigh(){
        memset(d,0,sizeof(d));
        len=0;
    }
} 
bign change(string str){
    bign a;
    a.len=str.size();
    for(int i=0;i<a.len;i++){
        a.d[i]=str[a.len-i-1]-0;
    }
    
return a; }

  大整數比較大小

    先判斷兩者的len大小,如果不鮮水果等,則以長的為大;如果相等,則從高位到低位進行比較,知道出現某一位不等,就可以判斷兩個數的大小。

    

int compare(bign a,bign b){
    if(a.len>b.len)    return 1;//a大 
    else if(a.len<b.len) return -1;//b大 
    else{
        for(int i=a.len-1;i>=0;i--){//從高位往低位比較 
            if(a.d[i]>b.d[i])
                
return 1;// 只要有一位a大,則a大 else if(a.d[i]<b.d[i]) return -1;//只要有一為a小,則a小 } return 0;//兩數相等 } }

  高精度加法

    用豎式的形式進行計算,對其中一位進行加法的步驟,將該位上的兩個數字與進位相加,得到的結果取個位數作為該位的結果,取十位數作為新的進位。

    bign add(bign a,bign b){

    bign c;
    int carry=0;//carry是進位
    for(int i=0
;i<a.len||i<b.len;i++){ int temp=a.d[i]+b.d[i]+carry;//當前位的兩個數與進位相加 c.d[c.len++]=temp%10;//取個位數作為該位結果 carry=temp/10; } if(carry != 0){ c.d[c.len++]=carry; } return c; }

  高精度減法

    保證a>b。否則,交換位置,減法後先輸出 “-”,再輸出結果‘。

    對某一步,比較被減位和減位,如果不夠減,則令被減位的高位減1、被減位+10,再進行減法;如果夠減,則一直減。最後一步要註意減法後高位可能有多余的0,要除去它們,但也要至少保證結果有一位數。

    

bign sub(bign a,bign b){
    bign c;
    for(int i=0;i<a.len||i<b.len;i++){
        if(a.d[i]<b.d[i]){
            a.d[i+1]--;//向高位借1
            a.d[i]+=10;
        }
        c.d[c.len++]=a.d[i]-b.d[i];//減法結果為當前位的結果
    }
    while(c.len-1>=1&&c.d[c.len-1]==0){
        c.len--;//去除高位的0,並且保證至少還有一位數。
    }
    return c;
}
bign before_sub(bign a,bign b){
    bign c;
    if(compare(a,b)==-1){//a比b小的話 
        c=sub(b,a);
        printf("-");
    }else{
        c=sub(a,b);
    }
    for(int i=c.len-1;i>=0;i--){
        printf("%d",c.d[i]);
    }
}

  高精度與低精度的乘法

    以147*35為例,把147看作一個高精度bign類型,35看為int類型。下面操作中,35始終為一個整體。

    1、7*35=245,取5作為該位的結果,高位部分24作為進位;

    2、4*35=140,加上進位24,等於164,取個位4作為該位的結果,高位16為進位;

    3、1*35=25,加上進位16,等於51,取1為該位的結果,高位5為進位。

    4、沒得乘了,進位不為0,把進位5直接作為該位的結果。

    

bign multi(bign a,int b){
    bign c;
    int carry=0;
    for(int i=0;i<a.len;i++){
        int temp=a.d[i]*b+carry;
        c.d[c.len++]=temp%10;
        carry=temp/10;
    }
    while(carry!=0){//與加法不同,乘法的進位可能不止以為,所以用循環 
        c.d[c.len++]=carry%10;
        carry/=10;
    }
    return c;
}

  高精度與低精度的除法

    取上一步的余數*10加上該步的位,得到該步的被除數,將其與除數比較:

      如果不夠除,則該位的商為0;

      如果夠除,則商為對應的商,余數即為對應的余數;

    最後一步應註意,減法後 高位可能有多余的0,要除去它們,但也保證結果至少有一位。

    

bign divide(bign a,int b,int& r){//r是上一步的余數。 
    bign c;
    c.len=a.len;//被除數的每一位和商的每一位是一一對應的,因此先令長度相等
    for(int i=a.len-1;i>=0;i--){//從高位開始 
        r=r*10+a.d[i];//當前位和上一步的余數組合 
        if(r<b)
            c.d[i]=0;//不夠除。商0;
        else{//夠除 
            c.d[i]=r/b;
            r=r%b;
        } 
    } 
    while(c.len-1>=1&&c.d[c.len-1]==0){
        c.len--;//去除高位的0,但保證至少有一位數存在。 
    }
    return c; 
}

大整數運算