C++大整数的加减乘除

  大整数除法迅飞星火和文心一言给的算法可参考,但结果都不对。

(注意,_string 你用C++  std::string 代替就行)

 加法:

/// <summary>
/// 无符号的两个整数相加 (参考自星飞星火)
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
/// 创建时间:2024-04-21    最后一次修改时间:2024-04-28 
_string _Integer::Add(const _string& num1, const _string& num2)
{
	/*
	std::string add(const std::string &num1, const std::string &num2) {
		int len1 = num1.size();
		int len2 = num2.size();
		int maxLen = std::max(len1, len2);
		std::string result(maxLen + 1, '0');

		int carry = 0;
		for (int i = 0; i < maxLen; i++) {
			int sum = carry;
			if (i < len1) {
				sum += num1[len1 - 1 - i] - '0';
			}
			if (i < len2) {
				sum += num2[len2 - 1 - i] - '0';
			}
			carry = sum / 10;
			sum %= 10;
			result[maxLen - i] = sum + '0';
		}
		if (carry > 0) {
			result[0] = carry + '0';
		} else {
			result.erase(result.begin());
		}

		return result;
	}
	*/
	 
	 
	int len1 = num1.std_size();
	int len2 = num2.std_size();
	int maxLen = _Math::Max(len1, len2);
	_string result(maxLen + 1, _t('0'));

	int carry = 0;
	for (int i = 0; i < maxLen; i++) {
		int sum = carry;
		if (i < len1) {
			sum += num1[len1 - 1 - i] - _t('0');
		}
		if (i < len2) {
			sum += num2[len2 - 1 - i] - _t('0');
		}
		carry = sum / 10;
		sum %= 10;
		result[maxLen - i] = sum + _t('0');
	}
	if (carry > 0) {
		result[0] = carry + _t('0');
	}
	else {
		//result.std_erase(result.std_begin());	 
		return result.SubStr(1, result.Length - 1);
	}

	return result;
}

减法:

/// <summary>
/// 无符号的两个整数相减,部分算法参考自星飞星火,但星火
/// 算的结果只有同位数相减才正确,注意:这里是假定是无符
/// 号两个整数相减。
/// 【中文】:两个数相减
/// 【英文】:Subtract two numbers
/// 百度文心一言和星飞星火结果不对。
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
/// 创建时间:2024-04-21    最后一次修改时间:2024-04-25 (已测试)
_string _Integer::Subtract(const _string& num1, const _string& num2, bool isCheckForamt)
{
	if (isCheckForamt){	Check(num1);	Check(num2);}
	/*
	*   星火给出的代码:
	* 
		int len1 = num1.size();
		int len2 = num2.size();
		int maxLen = std::max(len1, len2);
		std::string result(maxLen, '0');

		int iBorrow = 0;
		for (int i = 0; i < maxLen; i++) {
			int iDiff = num1[len1 - 1 - i] - num2[len2 - 1 - i] - iBorrow;
			if (iDiff < 0) {
				iDiff += 10;
				iBorrow = 1;
			}
			else {
				iBorrow = 0;
			}
			result[maxLen - 1 - i] = iDiff + '0';
		}

		result.erase(std::find_if(result.rbegin(), result.rend(), [](char ch) { return ch != '0'; }).base(), result.end());

		return result;
	*/
	  
	int len1 = num1.Length;
	int len2 = num2.Length;

	int maxLen = _Math::Max(len1, len2);
	  
	_string sResult(_t(""), maxLen + 1);

	//这里先比较字符串长度(数字位数)的大小
	if (len1 > len2){	 //num1 > num2
		int iBorrow = 0;
		for (int i = 0; i < len2; i++) {
			int iDiff = num1[len1 - 1 - i] - num2[len2 - 1 - i] - iBorrow;		 
			if (iDiff < 0) {
				iDiff += 10;
				iBorrow = 1;
			}
			else {
				iBorrow = 0;
			}
			sResult.Add(iDiff + _t('0'));
		} 

		if (iBorrow != 0){
			bool bBorrow = false;
			for (int i = len2; i < len1; i++){
				_char c = num1[len1 - i - 1];
				if (!bBorrow){
					if (c == _t('0')) {
						sResult.Add(_t('9'));
					}else{
						sResult.Add(c - 1);
						bBorrow = true;
					}
				}else{
					sResult.Add(c);
				}
			}
		}else{
			for (int i = len2; i < len1; i++){
				_char c = num1[len1 - i - 1];
				sResult.Add(c);
			}
		}	
		 
		sResult.TrimRight(_t('0'));  //除去尾部的0
		return sResult.Reversal();		 

	}else if(len1 == len2){//字符长度相等
		if (num1 > num2){
			int iBorrow = 0;
			for (int i = 0; i < len2; i++) {
				int iDiff = num1[len1 - 1 - i] - num2[len2 - 1 - i] - iBorrow;
				if (iDiff < 0) {
					iDiff += 10;
					iBorrow = 1;
				}
				else {
					iBorrow = 0;
				}
				sResult.Add(iDiff + _t('0'));
			}
			sResult.TrimRight(_t('0')); //除去尾部的0
			return sResult.Reversal();
		}else if(num1 == num2){
			return _t("0");
		}else{
			int iBorrow = 0;
			for (int i = 0; i < len2; i++) {
				int iDiff = num2[len1 - 1 - i] - num1[len2 - 1 - i] - iBorrow;
				if (iDiff < 0) {
					iDiff += 10;
					iBorrow = 1;
				}
				else {
					iBorrow = 0;
				}
				sResult.Add(iDiff + _t('0'));
			}
			 
			sResult.TrimRight(_t('0')); //除去尾部的0
			sResult.Add(_t('-'));
			
			return sResult.Reversal();
		}

	}else{  //len1 < len2  小数减大数
		int iBorrow = 0;
		for (int i = 0; i < len1; i++) {
			int iDiff = num2[len2 - 1 - i] - num1[len1 - 1 - i] - iBorrow;
			if (iDiff < 0) {
				iDiff += 10;
				iBorrow = 1;
			}
			else {
				iBorrow = 0;
			}
			sResult.Add(iDiff + _t('0'));
		}

		if (iBorrow != 0) {  //还需借一位
			bool bBorrow = false;
			for (int i = len1; i < len2; i++) {
				_char c = num2[len2 - i - 1];
				if (!bBorrow) {
					if (c == _t('0')) {
						sResult.Add(_t('9'));
					}
					else {
						sResult.Add(c - 1);
						bBorrow = true;
					}
				}
				else {
					sResult.Add(c);
				}
			}
		}
		else {
			for (int i = len1; i < len2; i++) {
				_char c = num2[len2 - i - 1];
				sResult.Add(c);
			}
		}

	
		sResult.TrimRight(_t('0'));
		sResult.Add(_t("-"));
		return sResult.Reversal();
	}

}

乘法

/// <summary>
/// 无符号的两个整数相剩 (参考自星飞星火)
/// 【中文】:两个数相乘
/// 【英文】:Multiplication of two numbers
/// </summary>
/// <param name="sNum1"></param>
/// <param name="sNum2"></param>
/// <returns></returns>
/// 创建时间:2024-04-21    最后一次修改时间:2024-04-21  (已测试)
_string _Integer::Multiplication(const _string& sNum1, const _string& sNum2,  bool isCheckForamt)
{
	if (isCheckForamt) { Check(sNum2);	Check(sNum2); }

	  /*
		int len1 = num1.size();
		int len2 = num2.size();
		std::vector<int> result(len1 + len2, 0);

		for (int i = len1 - 1; i >= 0; i--) {
			for (int j = len2 - 1; j >= 0; j--) {
				int product = (num1[i] - '0') * (num2[j] - '0');
				int sum = result[i + j + 1] + product;
				result[i + j + 1] = sum % 10;
				result[i + j] += sum / 10;
			}
		}

		std::string res;
		for (int num : result) {
			if (!res.empty() || num != 0) {
				res.push_back(num + '0');
			}
		}

		return res.empty() ? "0" : res;
	  */
	 
	size_t len1 = sNum1.Length;
	size_t len2 = sNum2.Length;

	_Array<_byte> result(len1 + len2);   //设置缓冲长度为 len1 + len2
	result.ZeroBufferAll();            //把缓冲区初始为0
	result.ResetLength(len1 + len2);  //重设长度

	/*
	123
	 11

		33    (3)  i = 2 j = 1(个位+3) i + j = 3 刚好是第4位 (3) i = 2 j = 0  (十位加3)
	   22
	  11	
	________
	  1353 
	*/
	for (int i = len1 - 1; i >= 0; i--) {
		for (int j = len2 - 1; j >= 0; j--) {
			int product = (sNum1[i] - '0') * (sNum2[j] - '0'); //总量 n * n
			int sum = result[i + j + 1] + product;  //
			result[i + j + 1] = sum % 10; 
			result[i + j] += sum / 10;
		}
	}

	_string sTmp(_t(""), result.Length);
	
	/*
	//15*15 = 0225  (第一位是0)
	size_t nStart = (*result.Data == 0) ? 1 : 0;
 
	for(size_t n = nStart; n < result.Length; ++n)		 
		sTmp.Add( *(result.Data + n) + 48);
	*/

	for (_byte b : result) {
		if (sTmp.Length > 0 || b != 0) {  //如果前面有非零的数字,则添加 
			sTmp.Add(b + 48);
		}
	}

	return sTmp.Length == 0 ? _t("0") : sTmp;
}

小整数整除

/// <summary>
/// sNum1 / sNum2 ,sNum1 的倍数受制于int所能表达的最大值
/// </summary>
/// <param name="sNum1"></param>
/// <param name="sNum2"></param>
/// <param name="isCheckForamt"></param>
/// <returns></returns>
/// 创建时间:2024-04-26    最后一次修改时间:2024-04-27  (已测试)
_Pair<int, _string> _Integer::SmallDiv(const _string& sNum1, const _string& sNum2, bool isCheckForamt)
{
	if (isCheckForamt) { Check(sNum1);	Check(sNum2); }

	if (sNum2 == _t("0"))
	{
		
		d.PrintError(_t("除数不能为零"), _t("_Integer::SmallDiv"));
		assert(false);
	}

	if (sNum1.Length < sNum2.Length)
		return _Pair<int, _string>(0, sNum1);

	if (sNum1.Length == sNum2.Length)
	{
		if (sNum1 > sNum2)
		{
			int nNear = (sNum1[0] - 48) / (sNum2[0] - 48 ) + 1;
		
			for (int n = nNear; n > 0; --n)
			{
				_string sn = ga.intToString(n);
				_string s = _Integer::Multiplication(sNum2, sn, false); //乘积
				_string r = _Integer::Subtract(sNum1, s, false); //余数


				if (r[0] == _t('-'))
				{

				}
				else if (r == _t("0"))
				{
					return _Pair<int, _string>(n, _t("0"));
				}	
				else
				{
					if (r.Length < sNum2.Length)
					{
						return _Pair<int, _string>(n, r);
					}
					else if (r.Length == sNum2.Length)
					{
						if (r < sNum2)
						{
							return _Pair<int, _string>(n, r);
						}
						else if (r == sNum2)
						{
							return _Pair<int, _string>(n + 1, _t("0"));
						}
					}
				}
			}
		}
		else if (sNum1 == sNum2)
		{
			return _Pair<int, _string>(1, _t("0"));
		}
		else
		{
			return _Pair<int, _string>(0, sNum1);
		}
	}
	else //sNum1.Length > sNum2.Length
	{
		int nNear =  _Math::pow(10, sNum1.Length - sNum2.Length) * (sNum1[0] -48 + 1) - 1;

		//_pin(nNear);

		for (int n = nNear; n > 0; --n)
		{
			_string sn = ga.intToString(n);
			_string s = _Integer::Multiplication(sNum2, sn, false); //乘积
			_string r = _Integer::Subtract(sNum1, s, false); //余数
				
			if (r[0] == _t('-'))
			{

			}
			else if (r == _t("0"))
			{
				return _Pair<int, _string>(n, _t("0"));
			}
			else
			{
				if (r.Length < sNum2.Length)
				{
					return _Pair<int, _string>(n, r);
				}
				else if (r.Length == sNum2.Length)
				{
					if (r < sNum2)
					{
						return _Pair<int, _string>(n, r);
					}
					else if (r == sNum2)
					{
						return _Pair<int, _string>(n + 1, _t("0"));
					}
				}

			}
		}
	}

	std::wcout <<  _t("错误:\n");
	_pcn(sNum1);
	_pcn(sNum2);

	assert(false);

	return _Pair<int, _string>(0, _t("错误!"));
}

大整数整除

/// <summary>
/// 【单词中英文对照】:两个数相除 - Divide two numbers
/// 
/// 百度文心一言和星飞星火结果不对。
/// </summary>
/// 创建时间:2024-04-25    最后一次修改时间:2024-04-27   (已测式,这个函数用了大约1整天时间,搞死人)
_string _Integer::Divide(const _string& sNum1, const _string& sNum2,bool isCheckForamt)
{	 
	if (isCheckForamt) { Check(sNum1);	Check(sNum2); }

	 
	if (sNum2 == _t("0"))
	{
		_string sError = _t("_string _Integer::Divide: 除数 sNum2 不能为零不能为 0  !");

		_cout << sError <<"\n";

		assert(false);		 
	}


	_string sResult(_t(""), sNum1.Length);
 
	//2024/4 nPos =  4-1 = 3     sSub = 24  Point = 2 - 1 - 1(2<4) = 0   s = sSub ""
	//2124/4 nPos =  4-1 = 3
	//2124/23 nPos = 4-2 - 1 = 1
	 
	_string sSub = sNum1.SubStr(0, sNum2.Length); //除数

	auto p = SmallDiv(sSub, sNum2, false);

	int nStart = sNum2.Length;

	//获取第一位,确保第一次 p.Fist不等于0
	if (p.First == 0) {

		sSub = sNum1.SubStr(0, sNum2.Length + 1);
	 
		p = SmallDiv(sSub, sNum2, false);

		nStart = sNum2.Length + 1;
	}
		

	for( int i = nStart; i <=  sNum1.Length; ++i){

		if (p.First > 0) {//商不为0 

			sResult.Add(_tostr(p.First));

			if (p.Second == _t("0")) { //商不为0,余数为0

				sSub = sNum1.SubStr(i, 1);		

			}else{	 //商不为0,余数不为0

				sSub = p.Second + sNum1.SubStr(i, 1);	
			}

			if(sSub.Length > 0)
				p = SmallDiv(sSub, sNum2, false);

		}else {     //--------------------------------商为零

			sResult.Add(_t("0"));

			if (p.Second == _t("0")) { //--------------商为0,余数为0
				sSub = sNum1.SubStr(i, 1); 
			}
			else {	//----------------------------商为0,余数不为0			
				sSub = p.Second + sNum1.SubStr(i, 1);
			}

			if (sSub.Length > 0)
				p = SmallDiv(sSub, sNum2, false);
		}		
	}
	
	return sResult;
	 
}

例子:


int main()
{
  
    for (int i = 1; i < 100; ++i)
    {
        _string s = _Integer::Divide(_t("2024"), _tostr(i));

        std::wcout << _t("2024/") << i << _t("\t\t");
        std::wcout << s << "\t";
        std::wcout << 2024 / i << "\n";
    }
 

    _string s1 = "88888888888888888888888888888888888888888888888888888888";

    _string s2 = "44444444444444444444444444444444444444444444444444444444";

    _string s3 = "23";

    _pcn(s1);
    _pcn(s2);
    _pcn(s3);

    _pcn(_Integer::Divide(s1,s2));

    _pcn(_Integer::Divide(s1, s3));

    _string s4 = _Integer::Divide(s1, s3);

    _pcn(s4);

    _pcn(_Integer::Divide(s2,s4));


    _pcn(_Integer::Multiplication(s4, s3));




    return 0;
     
}

执行结果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于大整数加减乘除运算,可以使用以下C语言代码进行描述: ```c #include<stdio.h> #include<string.h> #include<stdlib.h> #define maxn 1000 struct bign{ //定义结构体存储大整数 int d[maxn], len; bign() //结构体初始化函数 {memset(d,0,sizeof(d)); len=0;} }; bign change(char str[]) //将字符串转为大整数 { bign res; res.len=strlen(str); for(int i=0;i<res.len;i++) res.d[i]=str[res.len-1-i]-'0'; return res; } int compare(bign a, bign b) //比较两个大整数的大小 { if(a.len>b.len) return 1; else if(a.len<b.len) return -1; else { for(int i=a.len-1;i>=0;i--) if(a.d[i]>b.d[i]) return 1; else if(a.d[i]<b.d[i]) return -1; return 0; } } bign add(bign a, bign b) //大整数加法 { bign c; int carry=0; for(int i=0;i<a.len || i<b.len;i++) { int sum=a.d[i]+b.d[i]+carry; c.d[c.len++]=sum%10; carry=sum/10; } if(carry) c.d[c.len++]=carry; return c; } bign sub(bign a,bign b) //大整数减法 { bign c; for(int i=0,carry=0;i<a.len;i++) { int tmp=a.d[i]-carry-b.d[i]; if(tmp>=0) carry=0; else { carry=1; tmp+=10; } c.d[c.len++]=tmp; } while(c.len>1 && c.d[c.len-1]==0) c.len--; return c; } bign mul(bign a, int b) //大整数与小整数的乘法 { bign c; int carry=0; for(int i=0;i<a.len;i++) { int tmp=a.d[i]*b+carry; c.d[c.len++]=tmp%10; carry=tmp/10; } while(carry) //必须要判最高的一位有没有进位,否则漏了的话就少了一位 { c.d[c.len++]=carry%10; carry/=10; } return c; } bign mul(bign a, bign b) //大整数乘法 { bign c; c.len=a.len+b.len; for(int i=0;i<a.len;i++) for(int j=0;j<b.len;j++) c.d[i+j]+=a.d[i]*b.d[j]; for(int i=0;i<c.len;i++) { c.d[i+1]+=c.d[i]/10; //进位处理 c.d[i]%=10; } while(c.len>1 && c.d[c.len-1]==0) c.len--; return c; } bign divide(bign a, int b, int &r) //大整数除以小整数 { bign c; c.len=a.len; for(int i=a.len-1;i>=0;i--) { r=r*10+a.d[i]; if(r<b) c.d[i]=0; else { c.d[i]=r/b; r=r%b; } } while(c.len>1 && c.d[c.len-1]==0) c.len--; return c; } char* BignToString(bign a) //大整数转为字符串 { char* res=new char[maxn]; for(int i=0;i<a.len;i++) res[i]=a.d[a.len-1-i]+'0'; res[a.len]='\0'; return res; } int main() { char str1[maxn], str2[maxn]; int a,b; scanf("%s%s%d",str1,str2,&b); bign A=change(str1),B=change(str2),C,D,E; C=add(A,B); D=sub(A,B); E=mul(A,b); int r=0; C=divide(A,b,r); printf("%s\n%s\n%s\n%s\n",BignToString(C),BignToString(D),BignToString(E),BignToString(C)); return 0; } ``` 在程序中,使用结构体bign存储大整数,通过定义加法、减法、乘法、除法等运算函数,实现了大整数加减乘除运算。同时,还可以将大整数转为字符串输出,方便进行结果的输出和格式化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值