1. 程式人生 > >c++之大數 實現加減法

c++之大數 實現加減法

剛開始我見到網上的視訊教程裡有關於大數的實現,他是使用的連結串列來儲存數值,我開始嘗試也使用連結串列,但是失敗了,我又試著使用陣列來實現,經過兩天的奮戰,終於把這個類實現了,但遺憾的是隻實現了加減法,因為自己的知識有限,未能實現乘法除法運算,如果有大神知道如何實現,小弟我感激不盡。

直接上程式碼

#ifndef BIGNUMBER_H  
#define BIGNUMBER_H  
  
#include <iostream>  
#include <string>  
  
class BigNumber  
{  
public:  
    BigNumber();  
    BigNumber(std::string s_16);  
    BigNumber(const BigNumber &number);  
    /************************************************************************/  
    /* 改變數值的操作                                  */  
    /************************************************************************/  
    void setMaxValue();  
    void setMinValue();  
    BigNumber& operator++();//字首過載  
    const BigNumber operator++(int);//字尾過載  
    BigNumber& operator--();//字首過載  
    const BigNumber operator--(int);//字尾過載  
    const BigNumber& operator=(const BigNumber &number);  
    const BigNumber& operator+=(const BigNumber &number);  
    const BigNumber& operator-=(const BigNumber &number);  
  
    /************************************************************************/  
    /* 基本運算操作                                   */  
    /************************************************************************/  
    const BigNumber operator+(const BigNumber &number);  
    const BigNumber operator-(const BigNumber &number);  
    const BigNumber operator*(const BigNumber &number);//————————未完成  
    const BigNumber operator/(const BigNumber &number);//————————未完成  
    /************************************************************************/  
    /* 大小比較操作                                           */  
    /************************************************************************/  
    bool operator>(const BigNumber &number);  
    bool operator<(const BigNumber &number);  
    bool operator==(const BigNumber &number);  
    bool operator<=(const BigNumber &number);  
    bool operator>=(const BigNumber &number);  
  
    /************************************************************************/  
    /* 輸出操作                                     */  
    /************************************************************************/  
    friend std::ostream& operator<<(std::ostream &os, BigNumber &number);  
    friend std::istream& operator>>(std::istream &is, BigNumber &number);  
  
    const static unsigned int MaxValue = 0xFFFFFFFF;//一個無符號整數的最大值  
    const static unsigned int MinValue = 0x00000000;//一個無符號整數的最小值  
    const static unsigned int Size = 100;//儲存區大小  
private:  
    unsigned int data[Size];//儲存區  
  
    void _add(unsigned int data[], unsigned int posion);//進位操作  
    void _sub(unsigned int data[], unsigned int posion);//借位操作  
  
    unsigned char toBit4(char c);//字元轉數值  
    char fromBit4(unsigned char c);//數值轉字元  
  
    void set_Bit16(std::string s_16);  
    std::string get_Bit16();  
};  
  
#endif  
#include "BigNumber.h"  
  
/************************************************************************/  
/* 預設建構函式,初始數值為0                                            */  
/************************************************************************/  
BigNumber::BigNumber()  
{  
    setMinValue();  
}  
/************************************************************************/  
/* 以一個16進製表示的字串初始化大數                                   */  
/************************************************************************/  
BigNumber::BigNumber(std::string s_16)  
{  
    this->set_Bit16(s_16);  
}  
/************************************************************************/  
/* 拷貝建構函式                                           */  
/************************************************************************/  
BigNumber::BigNumber(const BigNumber &number)  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        this->data[index] = number.data[index];  
    }  
}  
/************************************************************************/  
/* 進位操作實際上是一個自加的過程,如果低位的數值自加後會溢位,則將     */  
/*  高一位的數也自加,否則就直接將當前數值自加後退出        */  
/************************************************************************/  
void BigNumber::_add(unsigned int data[], unsigned int posion)  
{  
    if (this->data[posion] == 0xFFFFFFFF)//如果當前位的值為最大值  
    {  
        if (posion == Size - 1)//如果到達最高位,則直接進行自加,不再進位  
        {  
            this->data[posion]++;  
            return;  
        }  
        _add(data, posion + 1);//通過將高位自加來表示進位  
        this->data[posion]++;  
    }  
    else//若不是最大值則進行自加  
    {  
        this->data[posion]++;  
    }  
}  
  
/************************************************************************/  
/* 借位操作實際上是一個自減的過程,如果低位的數值自減後會溢位,則將     */  
/*  高一位的數也自減,否則就直接將當前數值自減後退出        */  
/************************************************************************/  
void BigNumber::_sub(unsigned int data[], unsigned int posion)  
{  
    if (this->data[posion] == 0x00000000)//如果當前位的值為最小值  
    {  
        if (posion == BigNumber::Size - 1)//如果到達最高位,則直接進行自減,不再借位  
        {  
            this->data[posion]--;  
            return;  
        }  
        _sub(data, posion + 1);//通過將高位自減來表示借位  
        this->data[posion]--;  
    }  
    else//若不是最小值則進行自減  
    {  
        this->data[posion]--;  
    }  
}  
/************************************************************************/  
/* 將一個16進製表示的字元轉為數值                                       */  
/************************************************************************/  
unsigned char BigNumber::toBit4(char c)  
{  
    if (c <= '9'&&c >= '0')  
    {  
        return c - '0';  
    }  
    else if (c <= 'F'&&c >= 'A')  
    {  
        return c - 'A' + 10;  
    }  
    else if (c <= 'f'&&c >= 'a')  
    {  
        return c - 'a' + 10;  
    }  
    else  
    {  
        return 0xf0;  
    }  
}  
  
/************************************************************************/  
/* 將一個0~15之內的數值轉為16進製表示的字元                             */  
/************************************************************************/  
char BigNumber::fromBit4(unsigned char n)  
{  
    if (n <= 9 && n >= 0)  
    {  
        return n + '0';  
    }  
    if (n<=15&&n>=10)  
    {  
        return n + 'A' - 10;  
    }  
    return '\0';  
}  
  
/************************************************************************/  
/* 將數值轉為一個16進製表示的字串,並返回該字串                     */  
/************************************************************************/  
std::string BigNumber::get_Bit16()  
{  
    unsigned int index1 = BigNumber::Size - 1;  
    while (this->data[index1] == 0) //指向最高有效位  
    {  
        if (index1 == 0)  
        {  
            break;  
        }  
        index1--;  
    }  
    std::string s_16;  
    for (unsigned int i = index1 +1 ; i > 0;i--)  
    {  
        unsigned char bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0;  
        unsigned int temp = this->data[i - 1];//取出一個32位  
        /* 
        從高到低得到每一個4bit 
        */  
        bit7 = (temp >> 28) & 0xf;  
        bit6 = (temp >> 24) & 0xf;  
        bit5 = (temp >> 20) & 0xf;  
        bit4 = (temp >> 16) & 0xf;  
        bit3 = (temp >> 12) & 0xf;  
        bit2 = (temp >> 8) & 0xf;  
        bit1 = (temp >> 4) & 0xf;  
        bit0 = temp & 0xf;  
        s_16 += fromBit4(bit7);  
        s_16 += fromBit4(bit6);  
        s_16 += fromBit4(bit5);  
        s_16 += fromBit4(bit4);  
        s_16 += fromBit4(bit3);  
        s_16 += fromBit4(bit2);  
        s_16 += fromBit4(bit1);  
        s_16 += fromBit4(bit0);  
    }  
    return s_16;  
}  
  
/************************************************************************/  
/* 接受一個16進位制數的字串,將其存入轉為BigNumber                      */  
/************************************************************************/  
void BigNumber::set_Bit16(std::string s_16)  
{  
    this->setMinValue();//置零  
    unsigned int size = s_16.size();//補位,不夠32位則高位補零  
    if (size % 8 == 7)  
    {  
        s_16 = "0" + s_16;  
    }  
    else if (size % 8 == 6)  
    {  
        s_16 = "00" + s_16;  
    }  
    else if (size % 8 == 5)  
    {  
        s_16 = "000" + s_16;  
    }  
    else if (size % 8 == 4)  
    {  
        s_16 = "0000" + s_16;  
    }  
    else if (size % 8 == 3)  
    {  
        s_16 = "00000" + s_16;  
    }  
    else if (size % 8 == 2)  
    {  
        s_16 = "000000" + s_16;  
    }  
    else if (size % 8 == 1)  
    {  
        s_16 = "0000000" + s_16;  
    }  
    /************************************************************************/  
    /* 一次取8個字元,將其轉為32位無符號整數存入                            */  
    /************************************************************************/  
    for (unsigned int i = 0; i < s_16.size() / 8; ++i)  
    {  
        std::string c4 = s_16.substr(8 * i, 8 * i + 8);  
        unsigned int bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0;  
        bit7 = toBit4(c4[0]);  
        bit6 = toBit4(c4[1]);  
        bit5 = toBit4(c4[2]);  
        bit4 = toBit4(c4[3]);  
        bit3 = toBit4(c4[4]);  
        bit2 = toBit4(c4[5]);  
        bit1 = toBit4(c4[6]);  
        bit0 = toBit4(c4[7]);  
        this->data[s_16.size() / 8 - i - 1] |= bit7;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit6;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit5;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit4;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit3;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit2;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit1;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit0;  
    }  
}  
  
/************************************************************************/  
/* 設定數值為最小值                                         */  
/************************************************************************/  
void BigNumber::setMaxValue()  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        data[index] = 0xFFFFFFFF;  
    }  
}  
  
/************************************************************************/  
/* 設定數值為最大值                                         */  
/************************************************************************/  
void BigNumber::setMinValue()  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        data[index] = 0x00000000;  
    }  
}  
  
const BigNumber& BigNumber::operator=(const BigNumber &number)  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        this->data[index] = number.data[index];  
    }  
    return *this;  
}  
  
const BigNumber& BigNumber::operator+=(const BigNumber &number)  
{  
    *this = *this + number;  
    return *this;  
}  
  
const BigNumber& BigNumber::operator-=(const BigNumber &number)  
{  
    *this = *this - number;  
    return *this;  
}  
  
BigNumber& BigNumber::operator++()//字首過載,返回自加之後的值  
{  
    _add(this->data, 0);  
    return *this;  
}  
  
const BigNumber BigNumber::operator++(int)//字尾過載,返回自加之前的值  
{  
    BigNumber n = *this;  
    _add(this->data, 0);  
    return n;  
}  
  
BigNumber& BigNumber::operator--()//字首過載,返回自減之後的值  
{  
    _sub(this->data, 0);  
    return *this;  
}  
  
const BigNumber BigNumber::operator--(int)//字尾過載,返回自減之前的值  
{  
    BigNumber n = *this;  
    _sub(this->data, 0);  
    return n;  
}  
  
/******************************************************************************/  
/* 加法操作並不會改變兩個運算元本身的值,所以這裡儲存第一個加數的值到變數n    */  
/* 中,並將最終的和儲存到變數n中,返回變數n的值                    */  
/******************************************************************************/  
const BigNumber BigNumber::operator+(const BigNumber &number)  
{  
    BigNumber n = *this;  
    for (unsigned int index = 0; index < BigNumber::Size - 1; ++index)  
    {  
        if (BigNumber::MaxValue - this->data[index] < number.data[index])//如果需要進位則執行進位操作  
        {  
            n._add(n.data, index + 1);  
        }  
        n.data[index] = n.data[index] + number.data[index];//執行加法  
    }  
    n.data[BigNumber::Size - 1] = n.data[BigNumber::Size - 1] + number.data[BigNumber::Size - 1];//最高位不用進行進位  
    return n;  
}  
  
/******************************************************************************/  
/* 減法操作並不會改變兩個運算元本身的值,所以這裡儲存被減數的值到 變數n中     */  
/* 並將最終的差儲存到變數n中,返回變數n的值                                  */  
/******************************************************************************/  
const BigNumber BigNumber::operator - (const BigNumber &number)  
{  
    BigNumber n=*this;  
    for (unsigned int index = 0; index < BigNumber::Size - 1; ++index)  
    {  
        if (n.data[index] < number.data[index])//如果不夠減,就執行借位操作  
        {  
            n._sub(n.data, index + 1);//借位  
        }  
        n.data[index] = n.data[index] - number.data[index];//執行減法  
    }  
    n.data[BigNumber::Size - 1] = n.data[BigNumber::Size - 1] - number.data[BigNumber::Size - 1];//最高位不需要借位  
    return n;  
}  
  
/************************************************************************/  
/* 比較大小操作                                           */  
/************************************************************************/  
bool BigNumber::operator>(const BigNumber &number)  
{  
    unsigned int index1 = BigNumber::Size - 1;//分別指向最大下標  
    unsigned int index2 = BigNumber::Size - 1;  
    while (this->data[index1] == 0) //指向最高有效位  
    {  
        if (index1 == 0)  
        {  
            break;  
        }  
        index1--;  
    }  
    while (number.data[index2] == 0) //指向最高有效位  
    {  
        if (index2 == 0)  
        {  
            break;  
        }  
        index2--;  
    }  
    if (index1 > index2)  
    {  
        return true;  
    }  
    else if (index1 <index2)  
    {  
        return false;  
    }  
    else//當最高有效位的儲存區下標相同時,比較儲存區內的數值  
    {  
        if (this->data[index1] > number.data[index2])  
        {  
            return true;  
        }  
        else  
        {  
            return false;  
        }  
    }  
}  
  
bool BigNumber::operator<(const BigNumber &number)  
{  
    unsigned int index1 = BigNumber::Size - 1;//分別指向最大下標  
    unsigned int index2 = BigNumber::Size - 1;  
    while (this->data[index1] == 0) //指向最高有效位  
    {  
        if (index1 == 0)  
        {  
            break;  
        }  
        index1--;  
    }  
    while (number.data[index2] == 0) //指向最高有效位  
    {  
        if (index2 == 0)  
        {  
            break;  
        }  
        index2--;  
    }  
    if (index1 < index2)  
    {  
        return true;  
    }  
    else if (index1 > index2)  
    {  
        return false;  
    }  
    else//當最高有效位的儲存區下標相同時,比較儲存區內的數值  
    {  
        if (this->data[index1] < number.data[index2])  
        {  
            return true;  
        }  
        else  
        {  
            return false;  
        }  
    }  
}  
  
bool BigNumber::operator == (const BigNumber &number)  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        if (this->data[index] != number.data[index])//只要遇到儲存的數值不一樣就返回false  
        {  
            return false;  
        }  
    }  
    return true;  
}  
  
bool BigNumber::operator <= (const BigNumber &number)  
{  
    if (*this < number || *this == number)  
    {  
        return true;  
    }  
    return false;  
}  
  
bool BigNumber::operator >= (const BigNumber &number)  
{  
    if (*this > number || *this == number)  
    {  
        return true;  
    }  
    return false;  
}  
  
/************************************************************************/  
/* 過載輸出操作,輸出一個16進位制的字串,以0x開頭                       */  
/************************************************************************/  
std::ostream& operator<<(std::ostream &os, BigNumber &number)  
{  
    std::string s_16;  
    s_16 = number.get_Bit16();  
    os << "0x" << s_16;  
    return os;  
}  
/************************************************************************/  
/* 過載輸入操作,接收一個16進位制的字串,不需要0x開頭                   */  
/************************************************************************/  
std::istream& operator>>(std::istream &is, BigNumber &number)  
{  
    std::string s_16;  
    is >> s_16;  
    number.set_Bit16(s_16);  
    return is;  
}  

我本來不想使用c++的string來實現資料的輸出操作,但發現c++的iostream不能格式化輸出資料,所以就暫時使用string來實現資料的顯示。在實現類的過程中我也學到了很多知識。

理解了友元函式,友元函式只是在標頭檔案中宣告,友元函式並不是類的成員函式,但賦予了友元函式訪問類中私有成員的權利,以便多個類實現資料的共享(為了方便使用)

如何更好的以c++的風格過載,以及字首++和字尾++的區別,瞭解到為什麼字首++要比字尾++的效率要高,因為字首++返回的是物件的引用,而後綴++返回的是物件的值。

如果有時間,我會繼續查閱資料來實現大數的乘法和除法。

這裡貼出我想要實現的大數的記憶體模型