C++大數操作

今天想試着實現了一些C++大數的操作,忙活的時間不少,只不過就實現了加減法,乘除的方法只能有時間再來實現了。

說點心得,我下面大數的存儲方式很蠢(起初沒想着實現負數哭  後來寫減法的時候就想着也把負數的實現了奮鬥 實現起來的時候才發現自己給自己挖了一個大坑),下次實現大數的話,符號估計會單獨存儲,這樣處理乘除法也比較方便。


#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<memory.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>

#define mem(array)  memset((array),0,sizeof((array)))
#define Qsort(array,len,cmp) qsort(array,len,sizeof(array[0]),cmp)

#define inf 0x7fffffff

#define MAXN 1000

#define BigLen 1000
#define BigCarry 1000


using namespace std;



int compareBig(int *a, int *b);
int getTopDigits(int *a);
int getBigLen(int *a);
int* addBig(int *sum,int *a, int *b);
int* addSmall(int *sum,int *big, int small);
int* subtractBig(int *sub,int *a,int *b);
int* subtractSmall(int *sub,int *big, int small);
int outputBig(int *a);


int compareBig(int *a, int *b) /*** if a > b then return 1 while return -1 when a < b ,other case(a = b) return 0 */
{
    int aTopDigits = getTopDigits(a);
    int bTopDigits = getTopDigits(b);
    if(aTopDigits < 0 && bTopDigits > 0) /*** a is a negative number while b is a positive number */
        return -1;
    else if(aTopDigits > 0 && bTopDigits < 0) /*** a is a positive number while b is a negative number */
        return 1;

    /*** both a and b are negative number or positive number */
    int aLen = getBigLen(a);
    int bLen = getBigLen(b);
    int flag = (aTopDigits>0 ? 1 : -1);
    if(aLen < bLen)
        return -flag;
    else if(aLen > bLen)
        return flag;
    else{
        if(a[aLen] < b[aLen])
            return -1;
        else if(a[aLen] > b[aLen])
            return 1;

        for(int i = aLen-1; i >= 0; --i){
            if(a[i] < b[i])
                return -flag;
            else if(a[i] > b[i])
                return flag;
        }
    }
    return 0;

}

int getTopDigits(int *a)
{
    for(int i = BigLen-1; i >= 0; --i){
        if(a[i])
            return a[i];
    }
}

int getBigLen(int *a)
{
    int cnt;
    for(cnt = BigLen-1; cnt >= 0; --cnt){
        if(a[cnt])
            return cnt+1;
            //break;
    }
/***
    int digits;
    if(abs(a[cnt]) >= 100)
        digits = 3;
    else if(abs(a[cnt]) >= 10)
        digits = 2;
    else if(abs(a[cnt]) >= 0)
        digits = 1;
    else
        return -1;
    digits += cnt*(int)log10(BigLen);
    return digits;
    */

}

int* addBig(int *sum,int *a, int *b)  /*** sum = a + b */
{
    int aTopDigits = getTopDigits(a);
    int bTopDigits = getTopDigits(b);
    if(aTopDigits >= 0 && bTopDigits >= 0){ /*** a is a positive number while b is a positive number*/
        int t;
        int carry = 0;
        for(int i = 0; i < BigLen; ++i){
            t = a[i] + b[i] + carry;
            sum[i] = t % BigCarry;
            carry = t / BigCarry;
        }
        return sum;
    }
    else if(aTopDigits >= 0 && bTopDigits < 0){ /*** a is a positive number while b is a negative number*/
        int *t = new int[BigLen];
        for(int i = 0; i < BigLen; ++i)
            t[i] = b[i];
        int index = getBigLen(t)-1;
        t[index] = -t[index];
        subtractBig(sum,a,t);
        delete t;
        return sum;
    }
    else if(aTopDigits < 0 && bTopDigits >= 0){ /*** a is a negative number while b is a positive number*/
        return addBig(sum,b,a);
    }
    else if(aTopDigits < 0 && bTopDigits < 0){ /*** a is a negative number while b is a negative number*/
        int *t1 = new int[BigLen];
        int *t2 = new int[BigLen];
        for(int i = 0; i < BigLen; ++i){
            t1[i] = a[i];
            t2[i] = b[i];
        }
        int index_1 = getBigLen(t1)-1;
        int index_2 = getBigLen(t2)-1;
        t1[index_1] = -t1[index_1];
        t2[index_2] = -t2[index_2];
        addBig(sum,t1,t2);
        delete t1,t2;
        int index = getBigLen(sum) - 1;
        sum[index] = -sum[index];
        return sum;
    }
}

int* addSmall(int *sum,int *big, int small) /**** sum = big + small , compute a big number and a small number , big number must be greater than 0 */
{
    if(small < 0)
        return subtractSmall(sum,big,-small);
    int t = small % BigCarry;
    int carry = small / BigCarry;
    int index;
    for(index = 0; (t||carry) && index < BigLen; ++index){
        t += big[index];
        sum[index] = t % BigCarry;
        carry += t / BigCarry;
        t = carry % BigCarry;
        carry /= BigCarry;
    }
    while(index < BigLen)
        sum[index] = big[index++];

    return sum;
}

int* subtractBig(int *sub,int *a,int *b) /*** sub = a - b */
{
    int aTopDigits = getTopDigits(a);
    int bTopDigits = getTopDigits(b);
    if(aTopDigits >= 0 && bTopDigits >= 0){ /*** a is a positive number while b is a positive number*/
        int t;
        int carry = 0;
        for(int i = 0; i < BigLen; ++i){
            t = a[i] - b[i] - carry;
            t >= 0 ? carry = 0 : (carry = 1,t += BigCarry);
            sub[i] = t;
        }
        if(carry){
            for(int i = 0; i < BigLen; ++i)
                sub[i] = BigLen - sub[i] - 1;
            addSmall(sub,sub,1);
            for(int i = BigLen-1; i >= 0; --i)
                if(sub[i]){
                    sub[i] = -sub[i];
                    break;
                }
        }
        return sub;
    }
    else if(aTopDigits >= 0 && bTopDigits < 0){ /*** a is a positive number while b is a negative number*/
        int *t = new int[BigLen];
        for(int i = 0; i < BigLen; ++i)
            t[i] = b[i];
        int index = getBigLen(t)-1;
        t[index] = -t[index];
        addBig(sub,a,t);
        delete t;
        return sub;
    }
    else if(aTopDigits < 0 && bTopDigits >= 0){ /*** a is a negative number while b is a positive number*/
        int *t = new int[BigLen];
        for(int i = 0; i < BigLen; ++i)
            t[i] = a[i];
        int index = getBigLen(t)-1;
        t[index] = -t[index];
        addBig(sub,t,b);
        delete t;
        index = getBigLen(sub) - 1;
        sub[index] = -sub[index];
        return sub;
    }
    else if(aTopDigits < 0 && bTopDigits < 0){ /*** a is a negative number while b is a negative number*/
        int *t1 = new int[BigLen];
        int *t2 = new int[BigLen];
        for(int i = 0; i < BigLen; ++i){
            t1[i] = a[i];
            t2[i] = b[i];
        }
        int index_1 = getBigLen(t1) - 1;
        int index_2 = getBigLen(t2) - 1;
        t1[index_1] = -t1[index_1];
        t2[index_2] = -t2[index_2];

        subtractBig(sub,t2,t1);
        delete t1,t2;
        return sub;
    }
}

int* subtractSmall(int *sub,int *big, int small) /**** sub = big - small , compute a big number and a small number , big number must be greater than 0 */
{
    if(small < 0)
        return addSmall(sub,big,-small);
    int t = small % BigCarry;
    int carry = small / BigCarry;
    int index;
    for(index = 0; (t||carry) && index < BigLen; ++index){
        sub[index] = big[index] - t;
        /** sub[index] < 0 ? (sub[index] += BigCarry , ++carry) : ; */

        if(sub[index] < 0){
            sub[index] += BigCarry;
            ++carry;
        }
        t = carry % BigCarry;
        carry /= BigCarry;
    }
    while(index < BigLen)
        sub[index] = big[index++];

    return sub;
}




int outputBig(int *a)
{
    int index = -1;
    for(int i = BigLen-1; i >= 0; --i)
        if(a[i] != 0){
            index = i;
            printf("%d",a[i]);
            break;
        }
    for(int i = index-1; i >= 0; --i)
        printf("%03d",a[i]);
    if(index == -1)
        cout<<0;
    cout<<endl;
}


int a[MAXN];
int b[MAXN];
int c[MAXN];
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);


    mem(a);
    mem(b);
    mem(c);
    for(int i = 0; i < 10; ++i){
        a[i] = 555;
        b[i] = 555;
    }
    b[0] = 556;
    //b[10] = -1;
    a[10] = -1;


    //addBig(c,a,b);
    subtractBig(c,a,b);


    //cout<<compareBig(a,b)<<endl;

    //cout<<getTopDigits(a)<<endl;
    //cout<<getBigLen(a)<<endl;

    //addSmall(c,a,-566);
    //subtractSmall(c,a,0);



    //outputBig(c);

    //subtractBig(c,a,b);


    //subtractSmall(b,a,9999);
    //subtractSmall(a,a,999);

    outputBig(a);
    outputBig(b);
    outputBig(c);


    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章