C++大數操作Plus

按照上次的思路,最近又重新實現了加減法以及大數的乘法,除法的話,實現起來難度還有點大,有比較好的思路再來續寫吧。

 

 

#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 BigLen 10000     // length of the big number's array is BigLen
#define BigCarry 1000   // carry of the big number's array is BigCarry

/***

Assumption bigNum is a big number,
then the bigNum[0] is the lowest order digit while bigNum[BigLen-2] is the highest order digit and bigNum[BigLen-1] is sign bit.
bigNum[BigLen-1] is -1 means bigNum is a negative number while bigNum[BigLen-1] is 1 means bigNum is a positive number or zero.

We could define big number like this:
int bigNum[BigLen];

PS:I'm so sorry for my poor English.

 */

using namespace std;


bool add(int *sum, int *bigNum, int num);
bool add(int *sum, int *bigNumA, int *bigNumB);
int compare(int *bigNum,int num);
int compare(int *bigNumA,int *bigNumB);
int getTopPos(int *bigNum);
bool input(int *bigNum, char *str);
bool isBigNum(int *bigNum);
bool multiply(int *product, int *bigNum, int num);
bool multiply(int *product, int *bigNumA, int *bigNumB);
bool output(int *bigNum);
bool subtract(int *sub, int *bigNum, int num);
bool subtract(int *sub, int *bigNumA, int *bigNumB);
bool transBig2Num(int *bigNum, int &num);
bool transNum2Big(int *bigNum, int num);



bool isBigNum(int *bigNum)
{
    /***
    return true if the bigNum is legal big number while return false if not
    */
    for(int i = 0; i < BigLen-1; ++i)
        if(bigNum[i] < 0 || bigNum[i] >= BigCarry)
        return false;

    if(bigNum[BigLen-1] != 1 && bigNum[BigLen-1] != -1)
        return false;
    return true;
}



bool input(int *bigNum, char *str)
{
    /***
    giving a integer string and a pointer of array which length equal to BigLen
    the integer string have to be made up of integer figure from 0 to 9 and character '-' which means negative number
    the function will return true if the string is legal while return false if not

    */
    int len = strlen(str);
    if(len > (BigLen-1)*log10(BigCarry))        // the input string is too long so that the bigNum cannot save this number
        return false;
    int start = (str[0] == '-') ? 1 : 0;
    bool isdigit = true;
    for(int i = start; i < len; ++i){
        if(str[i] < '0' || str[i] > '9'){
            isdigit = false;
            break;
        }
    }
    if(!isdigit)
        return false;   // the input string have some non numerical character except '-'

    int index = 0;
    int num = 0;
    int power = 1;
    for(int i = len-1; i >= start; --i){
        num += (str[i]-'0') * power;
        power *= 10;
        if(power == BigCarry){
            bigNum[index++] = num;
            num = 0;
            power = 1;
        }
    }
    if(num)
        bigNum[index++] = num;
    for(int i = index; i < BigLen-1; ++i)
        bigNum[i] = 0;
    bigNum[BigLen-1] = start ? -1 : 1;

    if(bigNum[0] == 0 && getTopPos(bigNum) == 0)    // this will be work if input the string like "-00000"
        bigNum[BigLen-1] = 1;

    return true;
}



bool multiply(int *product, int *bigNumA, int *bigNumB)
{
    /***
    computing the product of both bigNumA and bigNumB
    */
    if(product != bigNumA && product != bigNumB){
        int topPosB = getTopPos(bigNumB);
        int productTemp[BigLen];
        int carry;
        mem(product);
        product[BigLen-1] = 1;
        for(int i = 0; i <= topPosB; ++i){
            int num = bigNumB[i];
            carry = 0;
            mem(productTemp);
            productTemp[BigLen-1] = 1;
            for(int j = 0; j < BigLen-1; ++j){
                carry += bigNumA[j] * num;
                productTemp[j] = carry % BigCarry;
                carry /= BigCarry;
           }

            if(carry)       // return false if overflow
                return false;

            int topPosProductTemp = getTopPos(productTemp);
            if(topPosProductTemp + i >= BigLen-1)   // overflow
                return false;

            for(int j = BigLen-2; j >= i; --j)
                productTemp[j] = productTemp[j-i];

            for(int j = 0; j < i; ++j)
                productTemp[j] = 0;

            if(!add(product,product,productTemp))
                return false;

        }
        delete productTemp;
        product[BigLen-1] = bigNumA[BigLen-1] * bigNumB[BigLen-1];
        return true;
    }
    else{
        int productTemp[BigLen];
        mem(productTemp);
        if(!multiply(productTemp,bigNumA,bigNumB))
            return false;
        for(int i = 0; i < BigLen; ++i)
            product[i] = productTemp[i];
        delete productTemp;
        return true;
    }
}



bool multiply(int *product, int *bigNum, int num)
{
    /***
    computing the product of both bigNum and num
    */
    int numSign;
    num = (num >= 0) ? (numSign = 1 , num) : (numSign = -1 , -num);
    if(num * BigCarry > inf){
        int small[BigLen];
        mem(small);
        transNum2Big(small,num);
        bool ans = multiply(product,bigNum,small);
        delete small;
        return ans;
    }
    else{
        int carry = 0;
        for(int i = 0; i < BigLen-1; ++i){
            carry += bigNum[i] * num;
            product[i] = carry % BigCarry;
            carry /= BigCarry;
        }
        product[BigLen-1] = bigNum[BigLen-1] * numSign;
        return carry ? false : true;    // return false if overflow

    }
}


bool subtract(int *sub, int *bigNum, int num)
{
    /***
    computing the different of both bigNum and num
    */
    // 這個好麻煩啊→_→ 不想寫了,簡單調用一下吧。。。(using English cannot express my feelings)
    // ignoring the above sentence, please
    int small[BigLen];
    mem(small);
    transNum2Big(small,num);
    bool ans = subtract(sub,bigNum,small);
    delete small;
    return ans;
}


bool add(int *sum, int *bigNum, int num)
{
    /***
    computing the sum of both bigNum and num
    */
    if(bigNum[BigLen-1] == 1){
        if(num >= 0){       // bigNum >= 0 && num >= 0
            int carry = num / BigCarry;
            int t = num % BigCarry + bigNum[0];
            carry += t / BigCarry;
            sum[0] = t % BigCarry;
            for(int i = 1; i < BigLen-1; ++i){
                t = carry + bigNum[i];
                sum[i] = t % BigCarry;
                carry = t / BigCarry;
            }
            sum[BigLen-1] = bigNum[BigLen-1];

            return carry ? false : true; // return false if overflow
        }
        else{       // bigNum >= 0 && num < 0
            return subtract(sum,bigNum,-num);
        }
    }
    else{
        if(num >= 0){       // bigNum < 0 && num >= 0
            bigNum[BigLen-1] = 1;
            bool ans = subtract(sum,bigNum,num);
            if(bigNum != sum)
                bigNum[BigLen-1] = -1;
            sum[BigLen-1] *= -1;
            return ans;
        }
        else{       // bigNum < 0 && num < 0
            bigNum[BigLen-1] = 1;
            bool ans = add(sum,bigNum,-num);
            bigNum[BigLen-1] = -1;
            sum[BigLen-1] = -1;
            return ans;
        }
    }
}



bool subtract(int *sub, int *bigNumA, int *bigNumB)
{
    /***
    computing the difference of both bigNumA and bigNumB
    */
    if(bigNumA[BigLen-1] == 1){
        if(bigNumB[BigLen-1] == 1){     // bigNumA >= 0 && bigNumB >= 0
            if(compare(bigNumA,bigNumB) >= 0){
                int carry = 0;
                for(int i = 0; i < BigLen-1; ++i){
                    carry += bigNumA[i] - bigNumB[i] + BigCarry;
                    sub[i] = carry % BigCarry;
                    carry = carry / BigCarry - 1;
                }
                sub[BigLen-1] = 1;
                return carry ? false : true;       // return false if overflow
            }
            else{
                bool ans = subtract(sub,bigNumB,bigNumA);
                sub[BigLen-1] = -1;
                return ans;
            }
        }
        else{       // bigNumA >=0 && bigNumB < 0
            bigNumB[BigLen-1] = 1;
            bool ans = add(sub,bigNumA,bigNumB);
            if(bigNumB != sub)
                bigNumB[BigLen-1] = -1;
            return ans;
        }
    }
    else{
        if(bigNumB[BigLen-1] == 1){     // bigNumA < 0 && bigNumB >=0
            bigNumA[BigLen-1] = 1;
            bool ans = add(sub,bigNumA,bigNumB);
            bigNumA[BigLen-1] = -1;
            sub[BigLen-1] = -1;
            return ans;
        }
        else{       // bigNumA < 0 && bigNumB < 0
            bigNumA[BigLen-1] = 1;
            bigNumB[BigLen-1] = 1;
            bool ans = subtract(sub,bigNumB,bigNumA);
            if(bigNumB != sub)
                bigNumB[BigLen-1] = -1;
            if(bigNumA != sub)
                bigNumA[BigLen-1] = -1;
            return ans;
        }
    }
}


bool add(int* sum, int *bigNumA, int *bigNumB)
{
    /***
    computing the sum of both bigNumA and bigNumB
    */
    if(bigNumA[BigLen-1] == bigNumB[BigLen-1]){     // both bigNumA and bigNumB are negative or positive numbers
        int carry = 0;
        for(int i = 0; i < BigLen-1; ++i){
            carry += bigNumA[i] + bigNumB[i];
            sum[i] = carry % BigCarry;
            carry /= BigCarry;
        }
        sum[BigLen-1] = bigNumA[BigLen-1];
        return carry ? false : true;       // return false if overflow
    }
    else{
        if(bigNumA[BigLen-1] == -1){
            bigNumA[BigLen-1] = 1;
            bool ans = subtract(sum,bigNumB,bigNumA);
            if(bigNumA != sum)
                bigNumA[BigLen-1] = -1;
            return ans;
        }
        else{
            bigNumB[BigLen-1] = 1;
            bool ans = subtract(sum,bigNumA,bigNumB);
            if(bigNumB != sum)
                bigNumB[BigLen-1] = -1;
            return ans;
        }
    }
}


bool transNum2Big(int *bigNum, int num)
{
    /***
    transferring a integer number to bigNum
    */
    bigNum[BigLen-1] = (num >= 0 ? 1 : -1);
    num = (num >= 0 ? num : -num);

    int index = 0;
    while(num > 0){
        bigNum[index++] = num % BigCarry;
        num /= BigCarry;
    }
    return true;
}


bool transBig2Num(int *bigNum, int &num)
{
    /***
    transferring a bigNum to a integer number
    */
    int topPos = getTopPos(bigNum);

    if(int(topPos*log10(BigCarry) + log10(bigNum[topPos])) >= int(log10(inf)))
        return false;       // return false if this num is not less than 1,000,000,000, but actually the biggest integer is 2,147,483,647(that is inf)


    num = bigNum[BigLen-1];
    num = num*bigNum[topPos];
    for(int i = topPos-1; i >= 0; --i)
        num = num*BigCarry + bigNum[i];
    return true;
}



int compare(int *bigNum, int num)
{
    /***
    if bigNum > num, then return 1
    if bigNum = num, then return 0
    if bigNum < num, then return -1
    */
    int bigSign = bigNum[BigLen-1];
    if(bigSign * num >= 0){
        int topPos = getTopPos(bigNum);
        int bigDigits = topPos*log10(BigCarry) + log10(bigNum[topPos]);
        int numDigits = log10(num);
        if(bigDigits != numDigits)
            return bigDigits > numDigits ? bigSign : -bigSign;


        int big;
        if(transBig2Num(bigNum,big)){
            if(big != num)
                return big > num ? 1 : -1;
            else
                return 0;
        }
        else{
            int small[BigLen];
            mem(small);
            transNum2Big(small,num);
            int ans = compare(bigNum,small);
            delete small;
            return ans;
        }
    }
    else{
        return num > 0 ? -1 : 1;
    }
}



int compare(int *bigNumA,int *bigNumB)
{
    /***
    if bigNumA > bigNumB, then return 1
    if bigNumA = bigNumB, then return 0
    if bigNumA < bigNumB, then return -1
    */
    if(bigNumA[BigLen-1] != bigNumB[BigLen-1])
        return bigNumA[BigLen-1] > bigNumB[BigLen-1] ? 1 : -1;

    // both bigNumA and bigNumB are positive numbers or negative numbers
    int sign = bigNumA[BigLen-1];
    int topPosA = getTopPos(bigNumA);
    int topPosB = getTopPos(bigNumB);
    if(topPosA != topPosB)
        return topPosA > topPosB ? sign : -sign ;

    for(int i = topPosA; i >= 0; --i)
        if(bigNumA[i] != bigNumB[i])
            return bigNumA[i] > bigNumB[i] ? sign : -sign ;

    return 0;
}


int getTopPos(int *bigNum)
{
    /***
    return the array index of bigNum's highest digits
    return 0 if the bigNum is zero
    */
    for(int topPos = BigLen-2; topPos >= 0; --topPos)
        if(bigNum[topPos])
            return topPos;
    return 0;
}
bool output(int *bigNum)
{
    /***
    output big number bigNum and carriage return is followed
    */

    if(!isBigNum(bigNum))
        return false;

    int topPos = getTopPos(bigNum);


    if(bigNum[BigLen-1] == -1 && (topPos || bigNum[topPos]))
        printf("-");
    printf("%d",bigNum[topPos]);

    char formatLen[2] = {char(log10(BigCarry)) + '0'};
    char format[6] = "%0";
    strcat(format,formatLen);
    strcat(format,"d");
    for(int i = topPos-1; i >= 0; --i)
        printf(format,bigNum[i]);
    printf("\n");
    return true;
}


歡迎各界大佬指出bug,非常感謝!

 

 

 

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