大位数类实现
为了解决大位数的密码学问题而编写的一个大位数的类,实现了加减乘除和比较符号的重载,运用链式结构存储大位数,效果还不错。除法参照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的话,欢迎评论跟我说。:)