C++ 整型大数运算(大整数运算)项目

C++ 整型大数运算项目

  • 一、项目介绍
  • 二、项目变量成员
  • 三、项目实现
    • 构造函数
    • 加法
    • 减法
    • 乘法
      • 先计算再进位
      • 边计算边进位
    • 除法与取模
    • 判断
    • 输入输出
  • 四、项目源代码展示
    • 在 Big_integer.h 中:
    • 在 Big_integer.cpp 中:
  • 五、测试准确性
  • 六、优化方向

一、项目介绍

整型大数运算,也就是大整数运算,是为了计算数据大小超过 long long 类型表示范围 [ -2 ^ 63, 2 ^ 63 - 1 ] 的整型数据。

整个项目最核心的目标是实现 四则运算 与 取模,外加 输入输出 与 两个大整数的大小判断

这里实现的四则运算借用的是小学时候使用的竖式计算,将思想转化为实际的代码。

以下代码环境为 VS 2022 C++。

二、项目变量成员

namespace my
{class Big_integer{private:enum Big_integer_sign				// 使用枚举体,防止赋值错误{positive = '+',negative = '-',};std::string _nums;					// 使用 string 存储具体数据Big_integer_sign _sign;				// 将符号单独列出,便于判断};
}
  1. 存储数字的容器使用 string ,方便其他数据转换为 string 再转为 Big_integer 。

  2. 将符号单独列出是因为用 string 存储符号会导致后面运算的附加判断很麻烦。

  3. 使用枚举体,防止赋值其他符号出现错误。

三、项目实现

构造函数

因为使用的是 string 存储数据,我们可以使用 to_string 函数将内置类型全部转换为 string 类型,不过要对 string 中的符号判断,例如出现 “-10” 这种数字前出现负号的 string 需要设计函数将符号与数字分离。

		Big_integer(const std::string& str = "0"):_sign(signExpressSolve(str)),_nums(str, signLastIndex(str) + 1){;}Big_integer(const Big_integer& number){_nums = number._nums;_sign = number._sign;}Big_integer(const long double number){*this = Big_integer(std::to_string((long long)number));}Big_integer(const double number){*this = Big_integer(std::to_string((long long)number));}Big_integer(const float number){*this = Big_integer(std::to_string((int)number));}Big_integer(const unsigned long long number){*this = Big_integer(std::to_string(number));}Big_integer(const long long number){*this = Big_integer(std::to_string(number));}Big_integer(const unsigned long number){*this = Big_integer(std::to_string(number));}Big_integer(const long number){*this = Big_integer(std::to_string(number));}Big_integer(const unsigned int number){*this = Big_integer(std::to_string(number));}Big_integer(const int number){*this = Big_integer(std::to_string(number));}Big_integer(const unsigned short number){*this = Big_integer(std::to_string(number));}Big_integer(const short number){*this = Big_integer(std::to_string(number));}Big_integer(const char* str){*this = Big_integer(std::string(str));}
		static Big_integer_sign signExpressSolve(const std::string& str){signed char sign = 1;for (auto e : str){if (e == negative){sign = -sign;}else if (e == positive){;}else{break;}}return sign == 1 ? positive : negative;}static size_t signLastIndex(const std::string& str){size_t index = -1;for (auto e : str){if (e == negative || e == positive){++index;}else{break;}}return index;}

加法

加法计算时只需模拟进位即可:
在这里插入图片描述
不过要注意符号,如下图:

正数 + 正数 和 负数 + 负数 在加法中不受影响,但是 正数 + 负数 和 负数 + 正数 需要转为减法,这意味其中一个数要 变号
在这里插入图片描述
这里先对 += 进行重载,因为返回的是 引用 ,会少一次拷贝

每位数计算后应该倒序存储,因为 string 空间是连续的,头插消耗大:

	Big_integer& Big_integer::operator+=(const Big_integer& number){if (_sign == positive && number._sign == negative)	// 正数 + 负数{										// number 变号使用减法,再变回来number.signChange();*this -= number;number.signChange();return *this;}if (_sign == negative && number._sign == positive)	// 负数 + 正数{										// this 变号使用减法,再变回来signChange();*this -= number;signChange();return *this;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int next = 0;							// 高位存储std::string copy;copy.reserve((len1 > len2 ? len1 : len2) + 5);while (len1 >= 0 || len2 >= 0 || next > 0){int num1 = len1 >= 0 ?		  _nums[len1--] - '0' : 0;int num2 = len2 >= 0 ? number._nums[len2--] - '0' : 0;int ret = num1 + num2 + next;		// 当前位数计算next = ret / 10;					// 进高位ret = ret % 10;						// 保留低位copy += (ret + '0');				// 存进结果}reverse(copy.begin(), copy.end());		// 翻转_nums = std::move(copy);				// 获取结果return *this;}
		void signChange() const{int* change = (int*)(&_sign);*change = (_sign == positive ? negative : positive);}

另外,与 内置类型 相加时会将 内置类型 隐式类型转换为 Big_integer,不用再写其他转换的函数。

接下来关于加法相关的函数都可以复用 += 运算符:

  1. + 重载运算符直接放在全局,等价于 大数 + 内置类型内置类型 + 大数

  2. 后置 和 前置 ++ 复用 += 即可。

		Big_integer operator++(int)				// 后置 ++{Big_integer temp = *this;++(*this);return temp;}Big_integer& operator++()				// 前置 ++{return *this += 1;}Big_integer operator+() const		// +数 等于一个表达式,这里只是闲的事不多加上的{return *this;}Big_integer operator+(const Big_integer& number1, const Big_integer& number2){												// 为方便使用,将 + 放在全局return Big_integer(number1) += number2;	}

减法

使用减法模拟时要注意谁的绝对值最大谁在前,保证 大 - 小,不然会出错:
在这里插入图片描述
同加法一样要注意符号,如下图:

正数 - 正数 和 负数 - 负数 在减法中不受影响,但是 正数 - 负数 和 负数 - 正数 需要转为加法,这意味其中一个数要 变号 。
在这里插入图片描述
注意,上面视图中的 9 - 12 是要将绝对值大的当 被减数,小的当 减数,意味着要额外判断:

	Big_integer& Big_integer::operator-=(const Big_integer& number){if (_sign == positive && number._sign == negative){									number.signChange();*this += number;number.signChange();return *this;}if (_sign == negative && number._sign == positive){signChange();*this += number;signChange();return *this;}int change = 1;						// this 是否变号int compare = justThanSize(number);	// 绝对值比较if (compare < 0){change = -1;					// this 的值小于 number,则 this 需要变号}else if (compare == 0)				// 特判解决当相减为零时出现负号情况,如:-3 + 3 = -0{return *this = 0;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int next = 0;						// 借位std::string copy;copy.reserve((len1 > len2 ? len1 : len2) + 5);while (len1 >= 0 || len2 >= 0){int num1 = len1 >= 0 ?		  _nums[len1--] - '0' : 0;int num2 = len2 >= 0 ? number._nums[len2--] - '0' : 0;int ret = change * (num1 - num2) + next;if (ret < 0)					// 当前位为负数,向上借 1{next = -1;					// 上一位被借 1,需要 -1ret += 10;					// 上一位借的 1 ,在当前位为 10 }else							// 不为负数则不用借{next = 0;}copy += (ret + '0');}//最高位去零while (copy.size() > 1 && copy[copy.size() - 1] == '0'){copy.pop_back();}if (change == -1)					// 变号{signChange();}reverse(copy.begin(), copy.end());_nums = std::move(copy);return *this;}
		int justThanSize(const Big_integer& number) const{int len1 = (int)_nums.size() - 1;int len2 = (int)number._nums.size() - 1;if (len1 != len2){return len1 - len2;}for (int i = 0; i <= len1; ++i){if (_nums[i] != number._nums[i]){return _nums[i] - number._nums[i];}}return 0;}

接下来处理于减法相关函数:

		Big_integer operator--(int){Big_integer temp = *this;--(*this);return temp;}Big_integer& operator--(){return *this -= 1;}Big_integer operator-() const		// -数 表示变号{Big_integer temp = *this;temp.signChange();return temp;}// 同理于 + 运算符函数Big_integer operator-(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) -= number2;}

乘法

乘法竖式计算有两种,第一种先将各位数结果保存,后进位。第二种是边乘边进位:
在这里插入图片描述
另外,对于结果存储位数大小是根据两个相乘的数的位数个数决定的:
在这里插入图片描述

所以两个不等于 0 的整数,其中一个位数为 x,另一个为 y,两者相乘时位数是相加的,则结果的位数 z 范围为 [ x + y - 1,x + y]。

这里为了保证计算,位数空间开到 x + y ,若位数数量为 x + y - 1,只需一次最高位去零即可。

对于符号的处理,因为先实现的是 *= 运算符函数,需要注意对 this 变号:
在这里插入图片描述

先计算再进位

	Big_integer& Big_integer::operator*=(const Big_integer& number){if (*this == 0 || number == 0)	// 有 0 时直接返回 0{								// 注意这里还没有实现大数的判断return *this = 0;}// 符号问题只需关注*thisif (_sign == positive && number._sign == negative){_sign = negative;}else if (_sign == negative && number._sign == negative){_sign = positive;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int maxN = (len1 + 1) + (len2 + 1);int index = maxN - 1;std::vector<int> copy(maxN, 0);			// signed char 存储会有溢出风险// 乘法while (len1 >= 0)						// 先将相乘结果存储{int i = maxN - index - 1;int num1 = len1 >= 0 ? _nums[len1] - '0' : 0;for (int line = len2; line >= 0; --line){int num2 = line >= 0 ? number._nums[line] - '0' : 0;copy[i] += num1 * num2;++i;}--index;--len1;}for (int i = 0; i < copy.size(); ++i)	// 后进位{if (copy[i] > 9){copy[i + 1] += copy[i] / 10;copy[i] %= 10;}copy[i] += '0';}// 最高位去零if (copy[copy.size() - 1] == '0'){copy.pop_back();}reverse(copy.begin(), copy.end());_nums = std::string(copy.begin(), copy.end());return *this;}

边计算边进位

	Big_integer& Big_integer::operator*=(const Big_integer& number){//if (*this == 0 || number == 0)	// 有 0 时直接返回 0//{//	return *this = 0;//}// 符号问题只需关注*thisif (_sign == positive && number._sign == negative){_sign = negative;}else if (_sign == negative && number._sign == negative){_sign = positive;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int maxN = (len1 + 1) + (len2 + 1);int index = maxN - 1;std::string copy(maxN, '0');// 乘法while (len1 >= 0){int next = 0;int i = maxN - index - 1;int num1 = len1 >= 0 ? _nums[len1] - '0' : 0;for (int line = len2; line >= 0; --line){int num2 = line >= 0 ? number._nums[line] - '0' : 0;int ret = num1 * num2 + next;next = ret / 10;ret = ret % 10;next +=   ((copy[i] - '0') + ret) / 10;copy[i] = ((copy[i] - '0') + ret) % 10 + '0';++i;}if (next > 0){copy[i] += next;}--index;--len1;}// 最高位去零if (copy[copy.size() - 1] == '0'){copy.pop_back();}reverse(copy.begin(), copy.end());_nums = std::move(copy);return *this;}

接下来处理 * 号:

	Big_integer operator*(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) += number2;}

除法与取模

除法与取模计算效率比较低下:
在这里插入图片描述
注意试乘方法从 0 到 9 ,可用二分进行小优化,要注意借用乘法、加法、减法时会将数字变号,所以将符号留到最后再判断:

	Big_integer& Big_integer::operator/=(const Big_integer& number){// 除数不能为零assert(number != 0);// 除数大于被除数直接为零if (justThanSize(number) < 0){return *this = 0;}Big_integer_sign sign1 = _sign;Big_integer_sign sign2 = number._sign;int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int condition = len1 - len2;		// 对齐int count = 0;std::string copy;copy.reserve(len1);while (len1 - len2 - count >= 0){int left = -1;int right = 10;while (left + 1 < right)		// 二分试乘{int mid = left + (right - left) / 2;if (justThanSize(number * mid * _pow(10, condition)) >= 0){left = mid;}else{right = mid;}}if (left != 0)					// 结果减(加)去试乘的数{if (_sign == number._sign){*this -= (left * number) * _pow(10, condition);}else{*this += (left * number) * _pow(10, condition);}}copy += (left + '0');++count;--condition;}// 除后符号放后面,防止加减乘过程中为零负号变为正号if (sign1 == positive && sign2 == negative){_sign = negative;}else if (sign1 == negative && sign2 == negative){_sign = positive;}else{_sign = sign1;}if (copy[0] == '0')					// 最高位去零{copy.erase(copy.begin());}_nums = std::move(copy);return *this;}

_pow 函数是位数对齐防止溢出,取模运算直接复用除乘减法即可:

	Big_integer Big_integer::_pow(const Big_integer& number, const int& index){if (index == 0){return 1;}Big_integer temp = _pow(number, index / 2);if (index % 2 == 0){return temp * temp;}else{return temp * temp * number;}}Big_integer& Big_integer::operator%=(const Big_integer& number){Big_integer temp = *this;temp /= number;return *this -= temp * number;}Big_integer operator/(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) /= number2;}Big_integer operator%(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) %= number2;}

判断

判断只需写好 == 与 < ,其他复用两者:

	bool operator!(const Big_integer& number){return number == 0;}bool operator!=(const Big_integer& number1, const Big_integer& number2){return !(number1 == number2);}bool operator>=(const Big_integer& number1, const Big_integer& number2){return !(number1 < number2);}bool operator> (const Big_integer& number1, const Big_integer& number2){return !(number1 <= number2);}bool operator<=(const Big_integer& number1, const Big_integer& number2){return number1 < number2 || number1 == number2;}bool operator==(const Big_integer& number1, const Big_integer& number2){if (number1._sign == number2._sign && number1._nums == number2._nums){return true;}else{return false;}}bool operator< (const Big_integer& number1, const Big_integer& number2){if (number1._sign == Big_integer::negative && number2._sign == Big_integer::positive){return true;}if (number1._sign == Big_integer::positive && number2._sign == Big_integer::negative){return false;}int lessNum = number1.justThanSize(number2);if (lessNum < 0){return number1._sign == Big_integer::positive ? true : false;}if (lessNum > 0){return number1._sign == Big_integer::positive ? false : true;}return false;}

输入输出

	std::ostream& my::operator<<(std::ostream& out, const my::Big_integer& number){if (number._sign == my::Big_integer::negative){out << '-';}out << number._nums;return out;}std::istream& my::operator>>(std::istream& in, my::Big_integer& number){std::string temp;in >> temp;number = temp;return in;}

四、项目源代码展示

在 Big_integer.h 中:

#pragma once #include <iostream>
#include <string>namespace my
{class Big_integer{private:enum Big_integer_sign				// 使用枚举体,防止赋值错误{positive = '+',negative = '-',};std::string _nums;					// 使用 string 存储具体数据Big_integer_sign _sign;				// 将符号单独列出,便于判断public:			// 构造函数Big_integer(const std::string& str = "0"):_sign(signExpressSolve(str)),_nums(str, signLastIndex(str) + 1){;}Big_integer(const Big_integer& number){_nums = number._nums;_sign = number._sign;}Big_integer(const long double number){*this = Big_integer(std::to_string((long long)number));}Big_integer(const double number){*this = Big_integer(std::to_string((long long)number));}Big_integer(const float number){*this = Big_integer(std::to_string((int)number));}Big_integer(const unsigned long long number){*this = Big_integer(std::to_string(number));}Big_integer(const long long number){*this = Big_integer(std::to_string(number));}Big_integer(const unsigned long number){*this = Big_integer(std::to_string(number));}Big_integer(const long number){*this = Big_integer(std::to_string(number));}Big_integer(const unsigned int number){*this = Big_integer(std::to_string(number));}Big_integer(const int number){*this = Big_integer(std::to_string(number));}Big_integer(const unsigned short number){*this = Big_integer(std::to_string(number));}Big_integer(const short number){*this = Big_integer(std::to_string(number));}Big_integer(const char* str){*this = Big_integer(std::string(str));}public:			// 加法Big_integer operator++(int)				// 后置 ++{Big_integer temp = *this;++(*this);return temp;}Big_integer& operator++()				// 前置 ++{return *this += 1;}Big_integer operator+() const		// +数 等于一个表达式,这里只是闲的事不多加上的{return *this;}Big_integer& operator+= (const Big_integer& number);public:			// 减法Big_integer operator--(int){Big_integer temp = *this;--(*this);return temp;}Big_integer& operator--(){return *this -= 1;}Big_integer operator-() const		// -数 表示变号{Big_integer temp = *this;temp.signChange();return temp;}Big_integer& operator-=(const Big_integer& number);public:Big_integer& operator*=(const Big_integer& number);Big_integer& operator/=(const Big_integer& number);Big_integer& operator%=(const Big_integer& number);friend std::ostream& operator<<(std::ostream& out, const Big_integer& number);friend std::istream& operator>>(std::istream& in, Big_integer& number);public:		// 判断friend bool operator==(const Big_integer& number1, const Big_integer& number2);friend bool operator< (const Big_integer& number1, const Big_integer& number2);public:void swap(Big_integer& number){std::swap(_nums, number._nums);std::swap(_sign, number._sign);}private:static Big_integer _pow(const Big_integer& number, const int& index);void signChange() const{int* change = (int*)(&_sign);*change = (_sign == positive ? negative : positive);}int justThanSize(const Big_integer& number) const;static Big_integer_sign signExpressSolve(const std::string& str);static size_t signLastIndex(const std::string& str);};bool operator!(const Big_integer& number);bool operator!=(const Big_integer& number1, const Big_integer& number2);bool operator>=(const Big_integer& number1, const Big_integer& number2);bool operator> (const Big_integer& number1, const Big_integer& number2);bool operator<=(const Big_integer& number1, const Big_integer& number2);Big_integer operator+(const Big_integer& number1, const Big_integer& number2);Big_integer operator-(const Big_integer& number1, const Big_integer& number2);Big_integer operator*(const Big_integer& number1, const Big_integer& number2);Big_integer operator/(const Big_integer& number1, const Big_integer& number2);Big_integer operator%(const Big_integer& number1, const Big_integer& number2);typedef Big_integer bint;		
}

在 Big_integer.cpp 中:

#include "Big_integer.h"
#include <cassert>namespace my
{int Big_integer::justThanSize(const Big_integer& number) const{int len1 = (int)_nums.size() - 1;int len2 = (int)number._nums.size() - 1;if (len1 != len2){return len1 - len2;}for (int i = 0; i <= len1; ++i){if (_nums[i] != number._nums[i]){return _nums[i] - number._nums[i];}}return 0;}Big_integer::Big_integer_sign Big_integer::signExpressSolve(const std::string& str){signed char sign = 1;for (auto e : str){if (e == negative){sign = -sign;}else if (e == positive){;}else{break;}}return sign == 1 ? positive : negative;}size_t Big_integer::signLastIndex(const std::string& str){size_t index = -1;for (auto e : str){if (e == negative || e == positive){++index;}else{break;}}return index;}Big_integer Big_integer::_pow(const Big_integer& number, const int& index){if (index == 0){return 1;}Big_integer temp = _pow(number, index / 2);if (index % 2 == 0){return temp * temp;}else{return (temp * temp) * number;}}Big_integer& Big_integer::operator+=(const Big_integer& number){if (_sign == positive && number._sign == negative)	// 正数 + 负数{										// number 变号使用减法,再变回来number.signChange();*this -= number;number.signChange();return *this;}if (_sign == negative && number._sign == positive)	// 负数 + 正数{										// this 变号使用减法,再变回来signChange();*this -= number;signChange();return *this;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int next = 0;							// 高位存储std::string copy;copy.reserve((len1 > len2 ? len1 : len2) + 5);while (len1 >= 0 || len2 >= 0 || next > 0){int num1 = len1 >= 0 ?		  _nums[len1--] - '0' : 0;int num2 = len2 >= 0 ? number._nums[len2--] - '0' : 0;int ret = num1 + num2 + next;		// 当前位数计算next = ret / 10;					// 进高位ret = ret % 10;						// 保留低位copy += (ret + '0');				// 存进结果}reverse(copy.begin(), copy.end());		// 翻转_nums = std::move(copy);				// 获取结果return *this;}Big_integer& Big_integer::operator-=(const Big_integer& number){if (_sign == positive && number._sign == negative){									number.signChange();*this += number;number.signChange();return *this;}if (_sign == negative && number._sign == positive){signChange();*this += number;signChange();return *this;}int change = 1;						// this 是否变号int compare = justThanSize(number);	// 绝对值比较if (compare < 0){change = -1;					// this 的值小于 number,则 this 需要变号}else if (compare == 0)				// 特判解决当相减为零时出现负号情况,如:-3 + 3 = -0{return *this = 0;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int next = 0;						// 借位std::string copy;copy.reserve((len1 > len2 ? len1 : len2) + 5);while (len1 >= 0 || len2 >= 0){int num1 = len1 >= 0 ?		  _nums[len1--] - '0' : 0;int num2 = len2 >= 0 ? number._nums[len2--] - '0' : 0;int ret = change * (num1 - num2) + next;if (ret < 0)					// 当前位为负数,向上借 1{next = -1;					// 上一位被借 1,需要 -1ret += 10;					// 上一位借的 1 ,在当前位为 10 }else							// 不为负数则不用借{next = 0;}copy += (ret + '0');}//最高位去零while (copy.size() > 1 && copy[copy.size() - 1] == '0'){copy.pop_back();}if (change == -1)					// 变号{signChange();}reverse(copy.begin(), copy.end());_nums = std::move(copy);return *this;}Big_integer& Big_integer::operator*=(const Big_integer& number){if (*this == 0 || number == 0)	// 有 0 时直接返回 0{return *this = 0;}// 符号问题只需关注*thisif (_sign == positive && number._sign == negative){_sign = negative;}else if (_sign == negative && number._sign == negative){_sign = positive;}int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int maxN = (len1 + 1) + (len2 + 1);int index = maxN - 1;std::string copy(maxN, '0');// 乘法while (len1 >= 0){int next = 0;int i = maxN - index - 1;int num1 = len1 >= 0 ? _nums[len1] - '0' : 0;for (int line = len2; line >= 0; --line){int num2 = line >= 0 ? number._nums[line] - '0' : 0;int ret = num1 * num2 + next;next = ret / 10;ret = ret % 10;next +=   ((copy[i] - '0') + ret) / 10;copy[i] = ((copy[i] - '0') + ret) % 10 + '0';++i;}if (next > 0){copy[i] += next;}--index;--len1;}// 最高位去零if (copy[copy.size() - 1] == '0'){copy.pop_back();}reverse(copy.begin(), copy.end());_nums = std::move(copy);return *this;}Big_integer& Big_integer::operator/=(const Big_integer& number){// 除数不能为零assert(number != 0);// 除数大于被除数直接为零if (justThanSize(number) < 0){return *this = 0;}Big_integer_sign sign1 = _sign;Big_integer_sign sign2 = number._sign;int len1 =		  _nums.size() - 1;int len2 = number._nums.size() - 1;int condition = len1 - len2;		// 对齐int count = 0;std::string copy;copy.reserve(len1);while (len1 - len2 - count >= 0){int left = -1;int right = 10;while (left + 1 < right)		// 二分试乘{int mid = left + (right - left) / 2;if (justThanSize(number * mid * _pow(10, condition)) >= 0){left = mid;}else{right = mid;}}if (left != 0)					// 结果减去试乘的数{if (_sign == number._sign){*this -= (left * number) * _pow(10, condition);}else{*this += (left * number) * _pow(10, condition);}}copy += (left + '0');++count;--condition;}// 除后符号放后面,防止加减乘过程中为零负号变为正号if (sign1 == positive && sign2 == negative){_sign = negative;}else if (sign1 == negative && sign2 == negative){_sign = positive;}else{_sign = sign1;}if (copy[0] == '0')					// 最高位去零{copy.erase(copy.begin());}_nums = std::move(copy);return *this;}Big_integer& Big_integer::operator%=(const Big_integer& number){Big_integer temp = *this;temp /= number;return *this -= temp * number;}Big_integer operator+(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) += number2;}Big_integer operator-(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) -= number2;}Big_integer operator*(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) *= number2;}Big_integer operator/(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) /= number2;}Big_integer operator%(const Big_integer& number1, const Big_integer& number2){return Big_integer(number1) %= number2;}bool operator! (const Big_integer& number){return number == 0;}bool operator!=(const Big_integer& number1, const Big_integer& number2){return !(number1 == number2);}bool operator>=(const Big_integer& number1, const Big_integer& number2){return !(number1 < number2);}bool operator> (const Big_integer& number1, const Big_integer& number2){return !(number1 <= number2);}bool operator<=(const Big_integer& number1, const Big_integer& number2){return number1 < number2 || number1 == number2;}bool operator==(const Big_integer& number1, const Big_integer& number2){if (number1._sign == number2._sign && number1._nums == number2._nums){return true;}else{return false;}}bool operator< (const Big_integer& number1, const Big_integer& number2){if (number1._sign == Big_integer::negative && number2._sign == Big_integer::positive){return true;}if (number1._sign == Big_integer::positive && number2._sign == Big_integer::negative){return false;}int lessNum = number1.justThanSize(number2);if (lessNum < 0){return number1._sign == Big_integer::positive ? true : false;}if (lessNum > 0){return number1._sign == Big_integer::positive ? false : true;}return false;}std::ostream& my::operator<<(std::ostream& out, const my::Big_integer& number){if (number._sign == my::Big_integer::negative){out << '-';}out << number._nums;return out;}std::istream& my::operator>>(std::istream& in, my::Big_integer& number){std::string temp;in >> temp;number = temp;return in;}
}

五、测试准确性

如有错误或Bug,可以评论区提出,谢谢!!!
在 test.cpp 中:

#include "Big_integer.h"
using namespace std;void testAddSub()
{long long a = 0;long long b = 0;my::bint c = 0;my::bint d = 0;int count1 = 0;int count2 = 0;for (int i = 0; i < 100000; ++i){a = ((rand() % 10000) * 100 + (rand() % 10000)) * 1000 + (rand() % 10000);b = ((rand() % 10000) * 100 + (rand() % 10000)) * 1000 + (rand() % 10000);c = a;d = b;if (c + d == a + b){++count1;}else{cout << "a = " << a << " " << "b = " << b << endl;cout << "c = " << c << " " << "d = " << d << endl;cout << "a + b == " << a + b << endl;cout << "c + d == " << c + d << endl;}if (c - d == a - b){++count2;}else{cout << "a = " << a << " " << "b = " << b << endl;cout << "c = " << c << " " << "d = " << d << endl;cout << "a - b == " << a - b << endl;cout << "c - d == " << c - d << endl;}}cout << "count1 == " << count1 << endl;cout << "count2 == " << count2 << endl;
}void testMul()
{int a = 0;int b = 0;my::bint c = 0;my::bint d = 0;int count = 0;for (int i = 0; i < 100000; ++i){int getSign1 = rand() % 2;int getSign2 = rand() % 2;a = rand();b = rand();if (getSign1 == 1){a = -a;}if (getSign2 == 1){b = -b;}c = a;d = b;if (c * d == a * b){++count;}else{cout << "a = " << a << " " << "b = " << b << endl;cout << "c = " << c << " " << "d = " << d << endl;cout << "a * b == " << a * b << endl;cout << "c * d == " << c * d << endl;}}cout << "count == " << count << endl;
}void testdiv()
{long long a = 0;long long b = 0;my::bint c = 0;my::bint d = 0;int count = 0;for (int i = 0; i < 10000; ++i){int getSign = rand() % 2;int getSign2 = rand() % 2;a = ((rand() % 10000) * 100 + (rand() % 10000)) * 1000 + (rand() % 10000);;b = ((rand() % 10000) * 100 + (rand() % 10000)) * 1000 + (rand() % 10000);;if (getSign == 1){a = -a;}if (getSign2 == 1){b = -b;}c = a;d = b;if (c / d == a / b){++count;}else{cout << "a = " << a << " " << "b = " << b << endl;cout << "c = " << c << " " << "d = " << d << endl;cout << "a / b == " << a / b << endl;cout << "c / d == " << c / d << endl;}}cout << "count == " << count << endl;
}void testImp()
{long long a = 0;long long b = 0;my::bint c = 0;my::bint d = 0;int count = 0;for (int i = 0; i < 100000; ++i){int getSign = rand() % 2;int getSign2 = rand() % 2;a = ((rand() % 10000) * 100 + (rand() % 10000)) * 1000 + (rand() % 10000);b = ((rand() % 10000) * 100 + (rand() % 10000)) * 1000 + (rand() % 10000);if (getSign == 1){a = -a;}if (getSign2 == 1){b = -b;}c = a;d = b;if (c % d == a % b){++count;}else{cout << "a = " << a << " " << "b = " << b << endl;cout << "c = " << c << " " << "d = " << d << endl;cout << "a % b == " << a % b << endl;cout << "c % d == " << c % d << endl;}}cout << "count == " << count << endl;
}int main()
{srand((unsigned int)time(NULL));testAddSub();testMul();testdiv();testImp();return 0;
}

六、优化方向

  1. 将数据倒着存储,可以减少每次计算后翻转效率的损失。

  2. 乘除使用更优的算法。

  3. 使用内置类型进行计算,提高计算速度,减少储存的浪费。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/459621.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++,STL 051(24.10.28)

内容 1.map容器的构造函数。 2.map容器的赋值操作。 运行代码 #include <iostream> #include <map>using namespace std;void printMap(map<int, int> &m) {for (map<int, int>::iterator it m.begin(); it ! m.end(); it){cout << &quo…

JavaSE笔记2】面向对象

目录 一、深刻认识面向对象 二、对象在计算机中的执行原理 三、this 四、构造器 五、封装 六、实体Javabean(实体类) 1. 是什么&#xff1f; 2. 实体类用来干什么&#xff1f; 七、成员变量和局部变量的区别 一、深刻认识面向对象 二、对象在计算机中的执行原理 三、this Java中…

通俗直观介绍ChatGPT背后的大语言模型理论知识

“AI 的 iPhone 时刻到来了”。非算法岗位的研发同学’被迫’学习 AI&#xff0c;产品岗位的同学希望了解 AI。但是&#xff0c;很多自媒体文章要么太严谨、科学&#xff0c;让非科班出身的同学读不懂&#xff1b;要么&#xff0c;写成了科幻文章&#xff0c;很多结论都没有充分…

基于SpringBoot的“时间管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“时间管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 管理员功能界面图 系统管理界面图…

云计算平台上的DevOps实践

文章目录 什么是DevOps云计算平台上的DevOps优势自动化部署弹性伸缩地理分布 实施DevOps的关键组件版本控制系统持续集成/持续交付工具配置管理工具监控和日志管理 实践案例使用AWS CodePipeline进行持续集成/持续交付利用AWS Auto Scaling实现弹性使用AWS CloudFormation进行基…

嵌入式学习-网络-Day03

嵌入式学习-网络-Day03 1.linux下IO模型及特点 1.1阻塞式IO 1.2非阻塞式IO 设置非阻塞&#xff1a; 1&#xff09;通过函数参数设置 2&#xff09;通过fcntl函数设置文件描述符属性 1.3信号驱动IO&#xff08;异步IO&#xff09; 1.4IO多路复用&#xff08;重点&#xff09; IO…

【HarmonyOS】判断应用是否已安装

【HarmonyOS】判断应用是否已安装 前言 在鸿蒙中判断应用是否已安全&#xff0c;只是通过包名是无法判断应用安装与否。在鸿蒙里新增了一种判断应用安装的工具方法&#xff0c;即&#xff1a;canOpenLink。 使用该工具函数的前提是&#xff0c;本应用配置了查询标签querySch…

【AI模特试衣整合包及教程】CatVTON引领虚拟试衣新时代

在这个数字时代&#xff0c;科技与时尚的融合日益紧密&#xff0c;为我们的生活带来前所未有的便利。今天&#xff0c;我们为您介绍一款革命性的虚拟试衣技术——CatVTON。它不仅为电商平台带来了全新的用户体验&#xff0c;更为设计师和消费者提供了无限创意的可能性。 一、Ca…

深度学习Pytorch-Tensor的属性、算术运算

深度学习Pytorch-Tensor的属性、算术运算 Tensor的属性Tensor的算术运算Pytorch中的in-place操作Pytorch中的广播机制Tensor的取整/取余运算Tensor的比较运算Tensor的取前k个大/前k小/第k小的数值及其索引Tensor判定是否为finite/inf/nan Tensor的属性 每一个Tensor对象都有以…

【强化学习】Actor-Critic算法

最近读论文看到了强化学习中的Actor-Critic算法。因此了解一下这方面的知识&#xff0c;并记录下来&#xff0c;以防忘记。文章中部分内容也借鉴了其他优秀的博主。 文章目录 一、简介二、策略梯度法&#xff08;Policy Gradient&#xff09;三、Q-Learning四、Actor-Critic 算…

【c语言】运算符汇总(万字解析)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C语言 目录 前言 一、c语言运算符的分类 二、各运算符的功能及使用 1. 算数运算符 - * / % 2. 位运算符 二进制和进制转换 二进制转十进制 十进制…

【Spring】Cookie与Session

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;计算机网络那些事 一、Cookie是什么&#xff1f; Cookie的存在主要是为了解决HTTP协议的无状态性问题&#xff0c;即协议本身无法记住用户之前的操作。 "⽆状态" 的含义指的是: 默认情况…

c++习题36-奇数单增序列

目录 一&#xff0c;题目 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;题目 给定一个长度为N&#xff08;不大于500&#xff09;的正整数序列&#xff0c;请将其中的所有奇数取出&#xff0c;并按升序输出。 输入描述 第1行为 N&#xff1b; 第2行为 N 个正整…

java中Scanner的nextLine和next方法

思考&#xff0c;输入1 2 3 4 5加上enter&#xff0c;输出什么 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int[][] m new int[2][2];for (int i 0; i < 2; i) {for (int j 0; j < 2;…

Spring Boot技术中小企业设备管理系统设计与实践

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…

重学SpringBoot3-怎样优雅停机

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-怎样优雅停机 1. 什么是优雅停机&#xff1f;2. Spring Boot 3 优雅停机的配置3. Tomcat 和 Reactor Netty 的优雅停机机制3.1 Tomcat 优雅停机3.2 Reac…

使用 Kafka 和 MinIO 实现人工智能数据工作流

MinIO Enterprise Object Store 是用于创建和执行复杂数据工作流的基础组件。此事件驱动功能的核心是使用 Kafka 的 MinIO 存储桶通知。MinIO Enterprise Object Store 为所有 HTTP 请求&#xff08;如 PUT、POST、COPY、DELETE、GET、HEAD 和 CompleteMultipartUpload&#xf…

fpga系列 HDL: 竞争和冒险 02

竞争和冒险 在 Verilog 设计中&#xff0c;竞争&#xff08;race conditions&#xff09;和冒险&#xff08;hazards&#xff09;是数字电路设计中不期望出现的现象&#xff0c;它们会影响电路的正确性。了解并解决竞争和冒险问题对于确保电路稳定运行非常重要。 竞争&#x…

尚硅谷-react教程-求和案例-数据共享(下篇)-完成数据共享-笔记

#1024程序员节&#xff5c;征文# public/index.html <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>redux</title></head><body><div id"root"></div></body> </html&…

MobileNetv2网络详解

背景&#xff1a; MobileNet v1中DW卷积在训练完之后部分卷积核会废掉&#xff0c;大部分参数为“0” MobileNet v2网络是由Google团队在2018年提出的&#xff0c;相比于MobileNet v1网络&#xff0c;准确率更高&#xff0c;模型更小 网络亮点&#xff1a; Inverted Residu…