zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【C++】C++大数之运算符重载

C++ 运算符 重载 大数
2023-09-11 14:20:18 时间

一、实验项目内容

Modify the “HugeInteger” Class. The new class should also provide the following overloaded operator capabilities:

. Overload the addition operator (+), the subtraction operator (-), the multiplication operator (*) and the division operator (/).
. Overload output operator (<<).
. Overload all the relational and equality operators.

You can use the following code to test your class design.

// HugeInt test program.
#include <iostream>
#include "Hugeint.h"
using namespace std;

int main()
{
   HugeInt n1( 7654321 );
   HugeInt n2( 7891234 );
   HugeInt n3( "99999999999999999999999999999" );
   HugeInt n4( "1" );
   HugeInt n5;

   cout << "n1 is " << n1 << "\nn2 is " << n2
      << "\nn3 is " << n3 << "\nn4 is " << n4
      << "\nn5 is " << n5 << "\n\n";

   n5 = n1 + n2;
   cout << n1 << " + " << n2 << " = " << n5 << "\n\n";

   cout << n3 << " + " << n4 << "\n= " << ( n3 + n4 ) << "\n\n";

   n5 = n1 + 9;
   cout << n1 << " + " << 9 << " = " << n5 << "\n\n";

   n5 = n2 + "10000";
   cout << n2 << " + " << "10000" << " = " << n5 << endl;
}

二、实验过程或算法

HugeInteger.h:

#ifndef HUGEINTER_H
#define HUGEINTER_H
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;

class HugeInteger{

private:
    string hugeInteger;                                  //声明私有成员hugeInteger

public:

    HugeInteger();                                       //default构造函数
    HugeInteger( string HugeInteger1);                    //构造函数1
    HugeInteger( int HugeInteger1);                       //构造函数2
    string getHugeInteger();                              //getting
    void setHugeInteger(const string& hugeInteger);       //setting

    //重载<<
    friend ostream& operator<<(ostream& output, const HugeInteger& aHugeInter) ;

    //重载+
    friend HugeInteger operator +(const HugeInteger& aHugeInteger, const HugeInteger& bHugeInteger);
    friend HugeInteger operator +(const HugeInteger& aHugeInteger, const string s);
    friend HugeInteger operator +(const HugeInteger& aHugeInteger, const int i);
    //重载-
    friend HugeInteger operator -(const HugeInteger& aHugeInteger, const HugeInteger& bHugeInteger);
    friend HugeInteger operator -(const HugeInteger& aHugeInteger, const string s);
    friend HugeInteger operator -(const HugeInteger& aHugeInteger, const int i);

    //重载*
    friend HugeInteger operator *(const HugeInteger& aHugeInteger,const HugeInteger& bHugeInteger);
    friend HugeInteger operator *(const HugeInteger& aHugeInteger,const string s);
    friend HugeInteger operator *(const HugeInteger& aHugeInteger, const int i);

    //重载/
    friend HugeInteger operator /(const HugeInteger& aHugeInteger,
            const HugeInteger& bHugeInteger);
    friend HugeInteger operator /(const HugeInteger& aHugeInteger,
            const string s);
    friend HugeInteger operator /(const HugeInteger& aHugeInteger, const int i);

};
#endif

HugeInteger.cpp:

#include "HugeInteger.h"
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;

HugeInteger::HugeInteger(){
    this->hugeInteger="null";
}

HugeInteger:: HugeInteger( string HugeInteger1){
    this->hugeInteger=HugeInteger1;
}
HugeInteger:: HugeInteger( int HugeInteger1){

    char t[256];
    sprintf(t, "%d", HugeInteger1);
    this->hugeInteger=t;
}

string HugeInteger::getHugeInteger() {
        return hugeInteger;
    }

void HugeInteger:: setHugeInteger(const string& hugeInteger) {
        this->hugeInteger = hugeInteger;
    }
//加法运算
char* getAddNumber(char* HugeInteger1,char* HugeInteger2) {
    int maxlen = max(strlen(HugeInteger1), strlen(HugeInteger2));
    //多两个字符,一个是结束符'/0',另一个保存当两个数最高位相加后有进位的情况
    char* p = new char[maxlen + 2];
    //结束符
    *(p + maxlen + 1) = '\0';
    //声明两个指针分别指向HugeInteger1和HugeInteger2的末尾,不含结束符
    char* pHugeInteger1 = HugeInteger1 + strlen(HugeInteger1) - 1;
    char* pHugeInteger2 = HugeInteger2 + strlen(HugeInteger2) - 1;
    int m = 0;
    int n = 0;
    //进位
    int c = 0;
    for (int i = maxlen; i > 0; i--) {
        m = n = 0;
        //因为当pHugeInteger1到达第一个字符时,即pHugeInteger1=a时,也要进行计算,所以这里用(pHugeInteger1-1)来判断
        //'0'的Asic是48,减去48转成数字
        if ((pHugeInteger1 + 1) != HugeInteger1) {
            m = *pHugeInteger1 - 48;
            pHugeInteger1--;
        }
        if ((pHugeInteger2 + 1) != HugeInteger2) {
            n = *pHugeInteger2 - 48;
            pHugeInteger2--;
        }
        //为p指针的第i个字符赋值
        *(p + i) = (m + n + c) % 10 + 48;
        //取得进位
        c = (m + n + c) / 10;
    }
    *p = 48 + c;

    if(*p=='0'){                        //如果结果的第一位是‘0’,表示没有进位
        return p+1;                     //返回第二位的指针,以去除第一位多余的0
    }
    return p;
}

//减法运算
char* getSubNumber(char* HugeInteger1,char* HugeInteger2){

    int isNegative=0;                   //定义结果是否为负数的标志,初始为0,不是负数

    int lHugeInteger1 = strlen(HugeInteger1), lHugeInteger2 = strlen(
            HugeInteger2);
    if (lHugeInteger1 > lHugeInteger2) { //HugeInteger1的位数大于HugeInteger2,则HugeInteger1大
        isNegative=0;
    } else if (lHugeInteger1 < lHugeInteger2) { //HugeInteger1的位数小于HugeInteger2,则HugeInteger1小
        char* temp = HugeInteger1;
        HugeInteger1 = HugeInteger2;
        HugeInteger2 = temp;

        isNegative=1;
    } else {                                                  //位数相等
        char* pHugeInteger1 = HugeInteger1;
        char* pHugeInteger2 = HugeInteger2;

        for (int c = 0; c < lHugeInteger1; c++) {                  //依次比较每一位数的大小
            if ((*(pHugeInteger1+c)) > (*(pHugeInteger2+c))) {         //不等,则比较大小
                isNegative=0;
                break;
            } else if ((*(pHugeInteger1+c)) <(*(pHugeInteger2+c))) {
                char* temp = HugeInteger1;
                HugeInteger1 = HugeInteger2;
                HugeInteger2 = temp;
                isNegative = 1;
                break;
            } else {                                          //相等继续
                continue;
            }
        }
    }

    int maxlen = max(strlen(HugeInteger1), strlen(HugeInteger2));
    //应为HugeInteger1始终大于HugeInteger2,不考虑被减数最高位不够减的情况
    char* p = new char[maxlen + 1];
    //最后一位是结束符
    *(p + maxlen) = '\0';
    //声明两个指针分别指向HugeInteger1和HugeInteger2的末尾,不包含结束符
    char* pHugeInteger1 = HugeInteger1 + strlen(HugeInteger1) - 1;
    char* pHugeInteger2 = HugeInteger2 + strlen(HugeInteger2) - 1;
    int m = 0;
    int n = 0;
    //借位位
    int c = 0;
    for (int i = maxlen - 1; i >=0; i--) {
        m = n = 0;
        //'0'的Asic是48,减去48转成数字
        if ((pHugeInteger1 + 1) != HugeInteger1) {
            m = *pHugeInteger1 - 48;
            pHugeInteger1--;
        }
        if ((pHugeInteger2 + 1) != HugeInteger2) {
            n = *pHugeInteger2 - 48;
            pHugeInteger2--;
        }
        //不够减,要借位
        if (m < n) {
            //为p指针的第i个字符赋值
            *(p + i) = 10 + m - n - c + 48;
            c = 1;
        } else {
            //虽然够减,但是如果再算是借走的一位,那么就小于0了
            if (m - n - c < 0)
                *(p + i) = 10 + m - n - c + 48;
            else {
                *(p + i) = m - n - c + 48;
                c = 0;
            }
        }
    }
    if (isNegative == 1) {
        if (*p == '0') {                        //如果结果的第一位是‘0’,表示没有进位
            char* temp = new char[maxlen];
            temp = p + 1;                            //返回第二位的指针,以去除第一位多余的0
            char* newp = new char[maxlen + 1];
            *newp = '-';                             //首地址带符号‘-’
            for (int i = 0; i < maxlen; i++) {
                *(newp + 1 + i) = *(temp+i);
            }
            return newp;                          //返回带符号的新字符串
        }
        else {
            char* temp2 = new char[maxlen+1];
            temp2 = p ;
            char* newp2 = new char[maxlen +2];
            *newp2 = '-';                             //首地址带符号‘-’
            for (int i = 0; i < maxlen+1; i++) {
                *(newp2 + 1 + i) = *(temp2+i);
            }
            return newp2;                          //返回带符号的新字符串
        }
    }
    else {
        if (*p == '0') {                        //如果结果的第一位是‘0’,表示没有进位
            return p+1;                     //返回第二位的指针,以去除第一位多余的0
        }
        return p;
    }
}

//乘法运算
char* getMultNumber(char* a, char* b) {
    int sizea = strlen(a);
    int sizeb = strlen(b);
    char* p = new char[sizea + sizeb + 1];
//两数相乘所得的积的位数最大为两个数位数只和,多申请一位放'\0'
    char* pA = a + sizea - 1;
    char* pB = b + sizeb - 1;
    int m = 0;
    int n = 0;
    //进位
    int c = 0;
//存放该位置原有的数
    int s = 0;
//记数
    int i = 0;
    int j = 0;
//具体实现过程详见说明文件
    for (i = 0; i < sizea; i++) {
        m = *(pA - i) - 48;
        c = 0;
        for (j = 0; j < sizeb; j++) {
            n = *(pB - j) - 48;
//判断该位置原来是否为0
            if ((*(p + i + j) >= '0') && (*(p + i + j) <= '9'))
                s = *(p + i + j) - 48;
            else
                s = 0;
            *(p + i + j) = (m * n + c + s) % 10 + 48;
            c = (m * n + c + s) / 10;
        }
        *(p + i + j) = 48 + c;
    }
    if (c > 0)
        *(p + i + j) = '\0';
    else
        *(p + i + j - 1) = '\0';

    int size1 = strlen(p) - 1;
    int size2 = (size1 + 1) / 2;
    char temp;
    for (int i = 0; i < size2; i++) {
        temp = p[i];
        p[i] = p[size1 - i];
        p[size1 - i] = temp;
    }
    return p;
}

//除法运算(保留个位)
string getDivNumber(const string &str1,const string &str2)  //  str1/str2
{
    int i;
    int length,len1,len2,len,index;
    bool flag;

    len1=str1.length();
    len2=str2.length();
    length=len1-len2;
    if(length<0) return "0";

    int *num1=new int[len1+1];
    int *num2=new int[len2+1];
    int *quotient=new int[length+2];

    memset(num1,0,sizeof(int)*(len1+1));
    memset(num2,0,sizeof(int)*(len2+1));
    memset(quotient,0,sizeof(int)*(length+2));

    for(i=len1-1,index=0;i>=0;i--)
    {
        num1[index++]=str1[i]-'0';
    }
    for(i=len2-1,index=0;i>=0;i--)
    {
        num2[index++]=str2[i]-'0';
    }

    while(true)
    {
        for(i=len1-1;i>=0;i--)
        {
            if(num1[i])
            {
                len1=i+1;
                break;
            }
            if(i==0) len1=0;
        }

        len=len1-len2;
        if(len<0) break;

        flag=false;
        index=0;

        for(i=len1-1;i>=len;i--)
        {
            if(num1[i]==num2[i-len]) continue;
            else if(num1[i]<num2[i-len])
            {
                flag=true;
                break;
            }
            else
            {
                break;
            }
        }

        if(flag) --len;
        if(len<0) break;

        while(++index)
        {
            flag=false;
            for(i=len1-1;i>=len;i--)
            {
                if(num1[i]==num2[i-len]) continue;
                else if(num1[i]<num2[i-len])
                {
                    flag=true;
                    break;
                }
                else
                {
                    break;
                }
            }
            if(flag)
            {
                --index;
                break;
            }

            for(i=len;i<len1;i++)
            {
                num1[i]-=num2[i-len];
                if(num1[i]<0)
                {
                    num1[i]+=10;
                    --num1[i+1];
                }
            }
        }
        if(index==0) break;
        else quotient[len]=index;
    }

    string ans;
    flag=false;
    for(i=length;i>=0;i--)
    {
        if(flag||quotient[i])
        {
            flag=true;
            ans+='0'+quotient[i];
        }
    }
    if(!flag) ans="0";

    delete [] num1;
    delete [] num2;
    delete [] quotient;

    return ans;
}

//重载<<
ostream& operator<<(ostream& output, const HugeInteger& aHugeInter) {

    output << aHugeInter.hugeInteger;
    return output;
}

//重载+
HugeInteger operator +(const HugeInteger& aHugeInteger,
        const HugeInteger& bHugeInteger) {

    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b = bHugeInteger.hugeInteger.c_str();

    return HugeInteger(getAddNumber((char*)a,(char*)b));

}
HugeInteger operator +(const HugeInteger& aHugeInteger, const string s){
    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b = s.c_str();

    return HugeInteger(getAddNumber((char*)a,(char*)b));
}
HugeInteger operator +(const HugeInteger& aHugeInteger, const int i){
    char t[256];
    sprintf(t, "%d", i);
    string temp=t;
    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b =temp.c_str();

    return HugeInteger(getAddNumber((char*)a,(char*)b));
}

//重载-
HugeInteger operator -(const HugeInteger& aHugeInteger,
        const HugeInteger& bHugeInteger) {

    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b = bHugeInteger.hugeInteger.c_str();

    return HugeInteger(getSubNumber((char*)a,(char*)b));

}
HugeInteger operator -(const HugeInteger& aHugeInteger, const string s){
    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b = s.c_str();

    return HugeInteger(getSubNumber((char*)a,(char*)b));
}

HugeInteger operator -(const HugeInteger& aHugeInteger, const int i){
    char t[256];
    sprintf(t, "%d", i);
    string temp=t;
    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b =temp.c_str();

    return HugeInteger(getSubNumber((char*)a,(char*)b));
}
//重载*
HugeInteger operator *(const HugeInteger& aHugeInteger,
        const HugeInteger& bHugeInteger) {

    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b = bHugeInteger.hugeInteger.c_str();

    return HugeInteger(getMultNumber((char*)a,(char*)b));

}
HugeInteger operator *(const HugeInteger& aHugeInteger, const string s){
    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b = s.c_str();

    return HugeInteger(getMultNumber((char*)a,(char*)b));
}

HugeInteger operator *(const HugeInteger& aHugeInteger, const int i){

    char t[256];
    sprintf(t, "%d", i);
    string temp=t;
    const char* a = aHugeInteger.hugeInteger.c_str();    //sting转换成char*
    const char* b =temp.c_str();

    return HugeInteger(getMultNumber((char*)a,(char*)b));
}

//重载/
HugeInteger operator /(const HugeInteger& aHugeInteger,
        const HugeInteger& bHugeInteger) {

    return HugeInteger(getDivNumber(aHugeInteger.hugeInteger,bHugeInteger.hugeInteger));

}
HugeInteger operator /(const HugeInteger& aHugeInteger, const string s){

    return HugeInteger(getDivNumber(aHugeInteger.hugeInteger,s));
}

HugeInteger operator /(const HugeInteger& aHugeInteger, const int i){

    char t[256];
    sprintf(t, "%d", i);
    string temp=t;

    return HugeInteger(getDivNumber(aHugeInteger.hugeInteger,temp));
}

测试类:

#include <iostream>
#include "HugeInteger.h"
using namespace std;

int main() {

    HugeInteger n1(7654321);
    HugeInteger n2(7891234);
    HugeInteger n3("99999999999999999999999999999");
    HugeInteger n4("1");
    HugeInteger n5;

    cout << "n1 is " << n1 << "\nn2 is " << n2 << "\nn3 is " << n3 << "\nn4 is "
            << n4 << "\nn5 is " << n5 << "\n\n";

    n5 = n1 + n2;
    cout << n1 << " + " << n2 << " = " << n5 << "\n\n";

    n5 = n1 - n2;              //小减大
    cout << n1 << " - " << n2 << " = " << n5 << "\n\n";
    n5 = n2- n1;               //大减小
    cout << n2<< " - " << n1<< " = " << n5 << "\n\n";

    n5 = n2 * n1;               //乘法
    cout << n2 << " * " << n1 << " = " << n5 << "\n\n";

    n5 = n2 / n1;               //除法  保留到整数
    cout << n2 << " / " << n1 << " = " << n5 << "\n\n";

    cout << n3 << " + " << n4 << "\n= " << (n3 + n4) << "\n\n";

    n5 = n1 + 9;               //与int类型运算
    cout << n1 << " + " << 9 << " = " << n5 << "\n\n";

    n5 = n2 + "10000";         //与string类型运算
    cout << n2 << " + " << "10000" << " = " << n5 << endl;

    n5 = n2 * "10000";         //乘法运算
    cout << n2 << " * " << "10000" << " = " << n5 << endl;

    n2= n5 /"10000";         //除法运算
    cout << n5<< " / " << "10000" << " = " << n2<< endl;

    return 0;
}

三、实验结果和截图