LONG_INT类的编写

大位数类实现

为了解决大位数的密码学问题而编写的一个大位数的类,实现了加减乘除和比较符号的重载,运用链式结构存储大位数,效果还不错。除法参照int型舍去小数点后的部分。

头文件

#ifndef _BIGINT_H
#define _BIGINT_H

#include<iostream>

//将大位数的每一位当成一个节点,节点存储数值
struct bigInt {
    int bit;
    bigInt * next;
};

class BigInt {
public:
    BigInt();                  //没有初始化
    BigInt(int);               //用int进行初始化
    BigInt(std::string);       //用string进行初始化,只接收数字字符
    BigInt(const BigInt & src);    //用BigInt进行初始化
    ~BigInt();                     //析构函数


    std::string toString() const;  //以字符串的形式显示数字
    void clear();                  //释放空间


    BigInt & operator=(const int & num);         //用int进行赋值    
    BigInt & operator=(const BigInt & src);      //同类间进行赋值

    BigInt & operator+=(const BigInt & src);     //重载运算符
    BigInt & operator+=(const int & num);
    BigInt & operator-=(const BigInt & src);
    BigInt & operator-=(const int & num);
    BigInt & operator*=(const BigInt & src);
    BigInt & operator*=(const int & num);
    BigInt & operator/=(const BigInt & src);
    BigInt & operator/=(const int & num);


    BigInt & operator++();              //重载单目运算符
    BigInt operator++(int);
    BigInt & operator--();
    BigInt operator--(int);
    BigInt operator-() const;

    //重载输出符
    friend std::ostream & operator<<(std::ostream & os, const BigInt & out);

    /*重载比较符号,这块函数只需写好相等和大于或小于两个函数即可,
      其他函数可以通过调用写好的两个函数进行解决*/
    friend bool operator==(const BigInt & ts, const BigInt & td);                 
    friend bool operator!=(const BigInt & ts, const BigInt & td);                 
    friend bool operator<(const BigInt & ts, const BigInt & td);                   
    friend bool operator<=(const BigInt & ts, const BigInt & td);
    friend bool operator>(const BigInt & ts, const BigInt & td);
    friend bool operator>=(const BigInt & ts, const BigInt & td);

    //重载+ - * /
    friend BigInt operator+(const BigInt & ts, const BigInt & td);  
    friend BigInt operator-(const BigInt & ts, const BigInt & td);
    friend BigInt operator*(const BigInt & ts, const BigInt & td);
    friend BigInt operator/(const BigInt & ts, const BigInt & td);
    //除法所用递归函数
    friend BigInt quotients(BigInt & dividend, BigInt & divisor);  


    //这一块的函数是为了能够与int型进行计较所做的重载
    friend bool operator==(const BigInt & ts, const int & num);                
    friend bool operator!=(const BigInt & ts, const int & num);                
    friend bool operator<(const BigInt & ts, const int & num);                  
    friend bool operator<=(const BigInt & ts, const int & num);
    friend bool operator>(const BigInt & ts, const int & num);
    friend bool operator>=(const BigInt & ts, const int & num);


    /*接下来的两块函数是为了能够与int型进行运算所做的重载,
    包括加减乘除以及运算顺序的问题写了这些重载,但其实顺
    序的问题只要写好一种情况就行了,另一种情况可以通过调
    用写好的那种情况的处理函数即可*/  
    friend BigInt operator+(const BigInt & ts, const int & num);              
    friend BigInt operator-(const BigInt & ts, const int & num);               
    friend BigInt operator*(const BigInt & ts, const int & num);              
    friend BigInt operator/(const BigInt & ts, const int & num);                

    friend BigInt operator+(const int & num, const BigInt & ts);
    friend BigInt operator-(const int & num, const BigInt & ts);
    friend BigInt operator*(const int & num, const BigInt & ts);
    friend BigInt operator/(const int & num, const BigInt & ts);

    int length();                       //获取数字长度
    bool get_symbol();                  //获取数字正负号
private:
    bigInt * number;                    //数字
    int numBit;                         //数字位数
    bool plus_or_minus;                 //符号

    void deepCopy(const BigInt & src);  //深复制
};

void error(std::string msg);            //出错时调用
BigInt int2BigInt(const int & num);     //将int转换为BigInt

#endif

cpp文件

#include "bigint.h"
#include <cctype>
#include <string>
#include <iostream>
using namespace std;

BigInt::BigInt() {
	number = NULL;
	numBit = 0;
	plus_or_minus = true;
}

BigInt::BigInt(int num) {
	if (num < 0) {                           //判断数字符号
		num = -num;
		plus_or_minus = false;
	}
	else
		plus_or_minus = true;

	bigInt * n = new bigInt;                 //获取数字最低位
	n->bit = num % 10;
	n->next = number;
	number = n;
	numBit++;

	bigInt * head = number;
	while (num /= 10) {                      //重复获取数字最低位
		bigInt * m = new bigInt;
		m->bit = num % 10;
		m->next = NULL;
		head->next = m;

		head = m;
		numBit++;
	}
}

BigInt::BigInt(std::string str) {
	if (str.length() == 0) error("The number is not exit!");       //字符串不能为空
	if (str[0] == '-') {                     //将符号转换为数字字符,同时判断符号
		str[0] = '0';
		plus_or_minus = false;
	}
	else if (str[0] == '+') {
		str[0] = '0';
		plus_or_minus = true;
	}
	else if (isdigit(str[0]))
		plus_or_minus = true;
	else
		error("This is not a number!");

	int low = 0;
	while (str[low] == '0')                 //计数数字第一个非零位前的零的个数
		low++;

	if (low == str.length()) {              //当数字为零时的处理
		bigInt * m = new bigInt;
		m->bit = 0;
		m->next = NULL;
		number = m;
		numBit = 1;
		plus_or_minus = true;
	}
	else {
		for (int i = str.length() - 1; i >= 0; i--) {        //判断字符串是否为纯数字
			if (!isdigit(str[i])) {
				error("This is not a number!");
			}
		}

		int len = str.length();                     //获取字符串最低位
		bigInt * n = new bigInt;
		n->bit = int(str[len - 1] - '0');
		n->next = number;
		number = n;
		numBit++;

		bigInt * head = number;
		for (int i = len - 2; i >= low; i--) {        //重复获取字符串最低位
			bigInt * m = new bigInt;

			m->bit = int(str[i] - '0');
			m->next = NULL;
			head->next = m;

			head = m;
			numBit++;
		}
	}
}

BigInt::~BigInt() {
	clear();
}

void BigInt::clear() {                        //释放空间
	while (number != NULL) {
		bigInt * n = number;
		if (n->next == NULL) {
			delete n;
			break;
		}
		while (n->next->next != NULL) {
			n = n->next;
		}
		delete n->next;
		n->next = NULL;
	}
	number = NULL;
	numBit = 0;
	plus_or_minus = true;
}

std::string BigInt::toString() const {                   
	std::string result = "";
	bigInt * head = number;
	while (head != NULL) {                        //获取数字,数字是倒置的
		result += char(head->bit + '0');
		head = head->next;
	}
	
	std::string revResult = "";
	for (int i = result.length() - 1; i >= 0; i--) {  //反转数字,同时去掉高位的无意义的零
		if (i == result.length() - 1 && i != 0) {
			while (result[i] == '0')
				i--;
		}
		revResult += result[i];
	}

	return revResult;
}

BigInt operator+(const BigInt & ts, const BigInt & td) {
    //同号进行相加
	if (ts.plus_or_minus == td.plus_or_minus) {   
	    //获取两者间的较大者
		BigInt result = !((ts > td) ^ ts.plus_or_minus) ? ts : td;  
		//较大者的数字部分
		bigInt * s = result.number;                                 
		//较小者的数字部分
		bigInt * d = !((ts > td) ^ ts.plus_or_minus) ? td.number : ts.number;    
		bool carry = false;                                         //进位

        //将两者同位的数字进行相加,设置进位
		while (d != NULL) {      
			int sum = s->bit + d->bit + int(carry);
			s->bit = sum % 10;
			carry = (sum > 9);
			s = s->next;
			d = d->next;
		}

        //判断是否存在进位
		if (carry) {                                
		    //若为9,则一直进位直到不为9
			while (s != NULL && s->bit == 9) {      
				s->bit = 0;
				s = s->next;
			}
			//若为空,则结果的最高位置为1,否则最高位加1
			if (s == NULL) {       
				bigInt * n = new bigInt;
				n->bit = 1;
				n->next = NULL;
				s = result.number;
				while (s->next != NULL)
					s = s->next;
				s->next = n;
				result.numBit++;
			}
			else {
				s->bit += 1;
			}
		}
		result.plus_or_minus = ts.plus_or_minus;              //判断结果符号
		return result;                                        //返回结果
	}
	else
		return ts - (-td);                                    //不同号视为相减
}

BigInt operator-(const BigInt & ts, const BigInt & td) {
    //同号进行相减
	if (ts.plus_or_minus == td.plus_or_minus) {  
	    //判断两者是否相等,若相等则直接零
		if (ts == td) {                          
			BigInt result = 0;
			return result;
		}
		//获取两者绝对值的较大者
		BigInt result = !((ts > td) ^ ts.plus_or_minus) ? ts : td;                
        //绝对值较大者的数字部分
		bigInt * s = result.number;                                               
        //绝对值较小者的数字部分
		bigInt * d = !((ts > td) ^ ts.plus_or_minus) ? td.number : ts.number;    
        //借位
		bool carry = false;                                             

        //将两者间同位的数字进行相减,设置借位
		while (d != NULL) {                
			int sum = s->bit - d->bit - int(carry);
			if (sum < 0) {
				sum += 10;
				carry = true;
			}
			else
				carry = false;
			s->bit = sum;
			s = s->next;
			d = d->next;
		}

        //判断是否有借位
		if (carry) {                                        
		    //若为0,则一直借位到非零位
			while (s != NULL && s->bit == 0) {              
				s->bit = 9;
				s = s->next;
			}
			if(s != NULL)                                   
				s->bit -= 1;
		}
		
		bigInt * head = result.number;
		int zero = 0;

        //计数数字最高位到第一个非零位间的零的个数
		while (head != NULL) {        
			if (head->bit == 0)
				zero++;
			else
				zero = 0;
			head = head->next;
		}

		BigInt corrResult(result.number->bit);
		//有意义的数字个数,除去高位无意义零的个数
		corrResult.numBit = result.numBit - zero;
		bigInt * h = result.number->next;
		bigInt * hc = corrResult.number;

        //除去高位无意义的零
		for (int i = 1; i < corrResult.numBit; i++) {     
			bigInt * m = new bigInt;
			m->bit = h->bit;
			m->next = NULL;
			hc->next = m;
			hc = m;
			h = h->next;
		}

		corrResult.plus_or_minus = (ts > td);              //判断符号
		return corrResult;                                 //返回修正后的结果
	}
	else
		return ts + (-td);                    //不同号视为相加

}

BigInt operator*(const BigInt & ts, const BigInt & td) {       
	int maxLen = (ts > td) ? ts.numBit : td.numBit;            //取得较大者的位数
	int minLen = (ts > td) ? td.numBit : ts.numBit;            //取得较小者的位数

	bigInt * s = (ts > td) ? ts.number : td.number;            //取得较大者的数字部分
	bigInt * d = (ts > td) ? td.number : ts.number;            //取得较小者的数字部分

	BigInt result(0);

	for (int i = 0; i < minLen; i++) {             
		if (d->bit == 0) {                         //去除低位为零值的乘法
			d = d->next;
			continue;
		}
		//以较小者的一位数乘以较大者的每一位数后将结果相加
		for (int j = 0; j < maxLen; j++) { 
			int sum = s->bit * d->bit;
			if (sum == 0) {                        //去除低位为零值的乘法
				s = s->next;
				continue;
			}
			BigInt tmp(sum);
			int zero = j + i;                       //判断当前两者相乘位数的位置,补零
			while (zero--) {
				bigInt * n = new bigInt;
				n->bit = 0;
				n->next = tmp.number;
				tmp.number = n;
				tmp.numBit++;
			}
			result = result + tmp;                   //将位数相乘的结果相加
			s = s->next;
		}
		s = (ts > td) ? ts.number : td.number;       //将较大者的指针复原
		d = d->next;
	}

	result.plus_or_minus = !(ts.plus_or_minus ^ td.plus_or_minus);     //判断符号

	return result;                                      //返回结果
}

BigInt operator/(const BigInt & ts, const BigInt & td) {             
	if (td == 0) error("The divisor couldn't be zero!");              //除数不能为零
	BigInt s = ts;                                                    //取两者的绝对值进行运算
	s.plus_or_minus = true;                                             
	BigInt d = td;
	d.plus_or_minus = true;
	BigInt result = quotients(s, d);                                  //以递归的函数进行相除运算
	result.plus_or_minus = !(ts.plus_or_minus ^ td.plus_or_minus);    //判断符号
	return result;                                                    //返回结果
}

BigInt & BigInt::operator=(const int & num) {            //以int进行深复制赋值
	BigInt src(num);
	if (this != &src) {
		clear();
		deepCopy(src);
	}
	return *this;
}
BigInt & BigInt::operator=(const BigInt & src) {          //以BigInt进行深复制赋值
	if (this != &src) {
		clear();
		deepCopy(src);
	}
	return *this;
}

BigInt::BigInt(const BigInt & src) {
	deepCopy(src);
}

std::ostream & operator<<(std::ostream & os, const BigInt & out) {           //重载输出符号
	if (out.plus_or_minus)
		return os << out.toString();                 
	else
		return os << "-" << out.toString();
}

void BigInt::deepCopy(const BigInt & src) {              //深复制,重新建立存储空间
	bigInt * n = new bigInt;
	n->bit = src.number->bit;
	n->next = NULL;
	number = n;

	bigInt * ts = number;
	bigInt * td = src.number->next;

	while (td != NULL) {
		bigInt * m = new bigInt;
		m->bit = td->bit;
		m->next = NULL;
		ts->next = m;

		ts = ts->next;
		td = td->next;
	}

	numBit = src.numBit;
	plus_or_minus = src.plus_or_minus;
}

void error(std::string msg) {                   //出错时调用的函数
	std::cout << msg << std::endl;
	exit(0);                                    //退出执行
}

bool operator==(const BigInt & ts, const BigInt & td) {            //重载==符号
	if (ts.numBit != td.numBit) return false;                      //判断位数
	if (ts.plus_or_minus != td.plus_or_minus) return false;        //判断符号
	
	bigInt * s = ts.number;                                        //判断每一位数
	bigInt * d = td.number;
	while (s != NULL) {
		if (s->bit != d->bit) return false;
		s = s->next;
		d = d->next;
	}
	return true;
}
bool operator!=(const BigInt & ts, const BigInt & td) {
	return !(ts == td);
}
bool operator<(const BigInt & ts, const BigInt & td) {             //重载<符号
	if (ts == td) return false;                                    //判断是否相等
	if (ts.plus_or_minus > td.plus_or_minus) return false;         //判断符号
	else if (ts.plus_or_minus < td.plus_or_minus) return true;     
	if (ts.numBit > td.numBit) return !ts.plus_or_minus;           //判断位数大小
	else if (ts.numBit == td.numBit) {                             //位数相同时判断每位数的大小
		std::string s = ts.toString();
		std::string d = td.toString();
		for (int i = 0; i < ts.numBit; i++) {
			if (s[i] > d[i]) return !ts.plus_or_minus;
			else if (s[i] < d[i]) return ts.plus_or_minus;
		}
	}
	return ts.plus_or_minus;
}
bool operator<=(const BigInt & ts, const BigInt & td) {
	return (ts < td) || (ts == td);
}
bool operator>(const BigInt & ts, const BigInt & td) {
	return !(ts <= td);
}
bool operator>=(const BigInt & ts, const BigInt & td) {
	return (ts > td) || (ts == td);
}

BigInt int2BigInt(const int & num) {        //int转BigInt
	BigInt tmp(num);
	return tmp;
}

bool operator==(const BigInt & ts, const int & num) {       //基于比较两个BigInt的重载
	BigInt td = int2BigInt(num);
	return ts == td;
}
bool operator!=(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts != td;
}
bool operator<(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts < td;
}
bool operator<=(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts <= td;
}
bool operator>(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts > td;
}
bool operator>=(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts >= td;
}

BigInt operator+(const BigInt & ts, const int & num) {       //基于运算两个BigInt的重载
	BigInt td = int2BigInt(num);
	return ts + td;
}
BigInt operator-(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts - td;
}
BigInt operator*(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts * td;
}
BigInt operator/(const BigInt & ts, const int & num) {
	BigInt td = int2BigInt(num);
	return ts / td;
}

BigInt operator+(const int & num, const BigInt & ts) {            //保证位置互换结果相同
	return ts + num;
}
BigInt operator-(const int & num, const BigInt & ts) {
	BigInt td = int2BigInt(num);
	return td - ts;
}
BigInt operator*(const int & num, const BigInt & ts) {
	return ts * num;
}
BigInt operator/(const int & num, const BigInt & ts) {
	BigInt td = int2BigInt(num);
	return td / ts;
}

//重载+= -= *= /=,考虑BigInt和int两种情况
BigInt & BigInt::operator+=(const BigInt & src) {             
	*this = *this + src;
	return *this;
}
BigInt & BigInt::operator+=(const int & num) {
	*this = *this + num;
	return *this;
}
BigInt & BigInt::operator-=(const BigInt & src) {
	*this = *this - src;
	return *this;
}
BigInt & BigInt::operator-=(const int & num) {
	*this = *this - num;
	return *this;
}
BigInt & BigInt::operator*=(const BigInt & src) {
	*this = *this * src;
	return *this;
}
BigInt & BigInt::operator*=(const int & num) {
	*this = *this * num;
	return *this;
}
BigInt & BigInt::operator/=(const BigInt & src) {
	*this = *this / src;
	return *this;
}
BigInt & BigInt::operator/=(const int & num) {
	*this = *this / num;
	return *this;
}

BigInt & BigInt::operator++() {                //重载单目运算符,考虑前置与后置
	*this = *this + 1;
	return *this;
}
BigInt BigInt::operator++(int) {
	BigInt tmp = *this;
	*this = *this + 1;
	return tmp;
}

BigInt & BigInt::operator--() {
	*this = *this - 1;
	return *this;
}
BigInt BigInt::operator--(int) {
	BigInt tmp = *this;
	*this = *this - 1;
	return tmp;
}

int BigInt::length() {              //获取数字位数
	return numBit;
}
bool BigInt::get_symbol() {         //获取符号
	return plus_or_minus;
}
BigInt BigInt::operator-() const {          //重载负号
	BigInt tmp = *this;
	tmp.plus_or_minus = !tmp.plus_or_minus;
	return tmp;
}

BigInt quotients(BigInt & dividend, BigInt & divisor) {          //除法所用的递归函数
	if (dividend < divisor) {                                    //被除数较小时返回0
		BigInt result(0);
		return result;
	}
	else if (dividend == divisor) {                               //两者相等时返回1
		BigInt result(1);
		return result;
	}
	else {                                  
		int maxLen = dividend.numBit;                    
		int minLen = divisor.numBit;

		BigInt div = divisor;
		BigInt result(1);

		if (maxLen > minLen) {
			for (int i = 0; i < (maxLen - minLen) - 1; i++) {          
            //将除数以10的倍数增大,直到除数的位数与被除数相差1位
				bigInt * m = new bigInt;
				m->bit = 0;
				m->next = div.number;
				div.number = m;
				div.numBit++;
				result *= 10;
			}

			if ((div * 10) <= dividend) { 
            //判断除数再增大10倍是否仍小于被除数,是则除数再增大10倍
				bigInt * m = new bigInt;
				m->bit = 0;
				m->next = div.number;
				div.number = m;
				div.numBit++;
				result *= 10;
			}
		}

		int i;
		for (i = 9; i > 0; i--) {       //将除数增大9~1倍与被除数进行比较,获取最接近的除数
			if ((div * i) <= dividend) {
				div *= i;
				break;
			}
		}
		result *= i;

		BigInt quotient;
		BigInt divi = dividend - div;                 //从被除数中减去除数
		quotient = result + quotients(divi, divisor); //递归调用,直到被除数小于或等于除数
		return quotient;                              //返回结果
	}
}

从实现加减再到实现乘除,从实现正数到加入符号实现负数,通过功能的不断加入、修整,这个类才一步步地成形,最后大致实现了所需的功能,编写的过程还是蛮有趣的,虽然有经过测试,但是不知道还会不会有bug,以后如果有用到的话出bug再说吧,如果有朋友使用了这个类出bug的话,欢迎评论跟我说。:)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值