大整数处理

针对精确表达浮点数 -- 编程之美那节处理大整数溢出的情况,写了这个代码:

对于加法,直接相加并在进行时考虑进位,也可以先相加,最后考虑进位问题。

减法,有加法类似,但此处未处理异号等情况,只考虑第一参数大于后面的,(考虑后面情况,需先判断大小关系,是否异号,是的话借用加法操作即可)。

乘法的话此处直接乘的未考虑优化其他的方法,加法雷同,先相加,最后考虑进位问题。

除法有点麻烦,的试商,调整余数,并且用减法来获得每位的商值!实现起来容易出问题。

代码如下:

#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>
using namespace std;

const int MAX_NUM = 1000;
template <class T>
 struct Huge_data
{
	T data[MAX_NUM];
	int len;
};
typedef Huge_data<int> HD;

void print_bigdata(HD &data);
void add(const HD &a,const HD &b,HD &res);
int cmp(const HD &a,const HD &b);
void subtract(const HD &a,const HD &b,HD &res);//保证a>=b,或者当a<b时,用b-a再更改负号
void str_to_hd(HD &a,string str);
void multi(const HD &a,const HD &b,HD &res);
void div(const HD a,const HD b,HD &res,HD &left);
int main()
{
//	HD first ={{1,2,3,4,5,6},6};

//	HD second={{9,9,9,9,5,4,3,2,1},9};

//	print_bigdata(first);
//	print_bigdata(second);
	/*
	add(first,second,second);
	print_bigdata(second);
    subtract(second,first,second);
	print_bigdata(second);
	*/
	HD first,second;
	HD res;
	string str_my;
	cin>>str_my;
	str_to_hd(first,str_my);
	 
	cin>>str_my;
	str_to_hd(second,str_my);
 
	//add(first,second,second);
	//print_bigdata(second);
    //subtract(second,first,second);
	//print_bigdata(second);
	multi(first,second,res);
	print_bigdata(res);
	div(first,second,res,first);
	print_bigdata(res);//商
	print_bigdata(first);//余数
	return 0;//正常退出!
}

void add(const HD &a,const HD &b,HD &res)
{
	int min_len = min(a.len,b.len);
	assert(min_len <= MAX_NUM);
	int carry = 0;
	for (int i = 0;i < min_len;i++)
	{
		int temp = a.data[i] + b.data[i] + carry;
		carry = 0;
		if (temp >= 10)//尽量不要取某
		{
			res.data[i] = temp - 10 ;
			carry = 1;
		}
		else
		{
			res.data[i] = temp;
		}
	}
	int max_len = max(a.len,b.len);

	assert(max_len <= MAX_NUM);
	const HD *c;
	if (a.len > b.len)
	{
		c = &a;
	}
	else
	{
		c = &b;
	}
	for (int j = min_len; j < max_len;j++)
	{
		int temp = c->data[j] +  carry;
		carry = 0;
		if (temp >= 10)//尽量不要取某
		{
			res.data[j] = temp - 10 ;
			carry = 1;
		}
		else
		{
			res.data[j] = temp;
		}
	}
	res.len = max_len;
	//最后是否有进位
	if(carry == 1)
	{
		assert(max_len+1 <= MAX_NUM);
		res.data[max_len] = 1;
		res.len = max_len+1;
	}

}
void print_bigdata(HD &hdata)
{
	for (int i = hdata.len-1;i >=0;i--)
	{
		cout<<hdata.data[i];
	}
	cout<<endl;
}
void str_to_hd(HD &a,string str)
{
	a.len = str.size();
	for(int i = str.size()-1;i >= 0;i--)
	{
		a.data[i] = str[str.size()-1-i]-'0';
	}
	
	if (a.len == 0)//默认为0
	{
		a.len = 1;
		a.data[0] = 0;
	}
}

int cmp(const HD &a,const HD &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--)
		{
			return a.data[i]-b.data[i];
		}
	}
	return -1;
}

void subtract(const HD &a,const HD &b,HD &res)//保证a>=b,或者当a<b时,用b-a再更改负号
{
	assert(cmp(a,b)>=0);

	int min_len = min(a.len,b.len);
	assert(min_len <= MAX_NUM);
	int carry = 0;
	for (int i = 0;i < min_len;i++)
	{
		int temp = a.data[i] - b.data[i] - carry;
		carry = 0;
		if (temp < 0)//尽量不要取某
		{
			res.data[i] = temp + 10 ;
			carry = 1;
		}
		else
		{
			res.data[i] = temp;
		}
	}
	int max_len = max(a.len,b.len);

	assert(max_len <= MAX_NUM);
	const HD *c;
	if (a.len > b.len)
	{
		c = &a;
	}
	else
	{
		c = &b;
	}
	for (int j = min_len; j < max_len;j++)
	{
		int temp = c->data[j] -  carry;
		carry = 0;
		if (temp < 0)//尽量不要取某
		{
			res.data[j] = temp + 10 ;
			carry = 1;
		}
		else
		{
			res.data[j] = temp;
		}
	}
	res.len = max_len;
	//最后是否有借位,不可能发生!!因a>=b
	//(carry == 1)
	//但的处理长度,可能a == b全0

	while(res.len>1&&res.data[res.len-1] == 0)res.len--;//处理头为长度,且保证长度大于等于1

}

void multi(const HD &a,const HD &b,HD &res)
{
	memset(&res,0,sizeof(HD));
	for(int i = 0; i < a.len;i++)
	{
		for(int j = 0; j < b.len;j++)
		{
			res.data[i+j] += a.data[i]*b.data[j];
		}
	}

	int carry = 0;
	for(int k = 0; k < a.len+b.len;k++)
	{
		int temp = (res.data[k]+carry);
		carry = temp / 10;
		res.data[k] = temp % 10;
	}
	int count = a.len+b.len;
	while(carry > 0)//有进位
	{
		res.data[count++] = carry % 10;
		carry = carry / 10;	
	}
	res.len = count --;
	//去除一些最高位为0的情况
	while(res.len>1&&res.data[res.len-1] == 0)res.len--;//处理头为长度,且保证长度大于等于1
}

void div(const HD a,const HD b,HD &res,HD &left)//left 必须是干净的值否则会影响
{
	memset(&left,0,sizeof(HD));
	memset(&res,0,sizeof(HD));
	left.len = 0;
	left.data[0] = 0;//理解开头的处理(由于余数小,则i++,使得余数left变大,直达大于除数,开始处理)
	for(int i = a.len-1; i >= 0;i--)
	{
		
			// 以下处理余数
		for(int j = left.len -1;j >= 0;j--)//处理余数向右移动
		{
			left.data[j+1] = left.data[j] ;
		}
		left.len++;//长度加1
		//给予被除数的一位
		left.data[0] = a.data[i];//放在末尾位置
		//res.data[i] = 0;//清0
		//当余数大于除数就处理,-- 通过减法实现的除法
		int val;
		while((val = cmp(left,b)) >= 0)
		{
			subtract(left,b,left);
			//就是此处处理有点问题!改正 或者在处理余数时处理!!!
			if(left.len == 1&&left.data[0]== 0)//减法会出来一个0,使有长度!
			{
				left.len = 0;
				left.data[0] = 0;
			}
			res.data[i]++;//商加加 (可以第一次处理时记住长度,或下面处理)
			if(val == 0)
			{
				break;
			}
			
		}
	}

	if(left.len == 0)
	{
		left.len = 1;
	    left.data[0] = 0;
	}
	res.len = a.len;
	while(res.len > 1 && res.data[res.len-1] == 0 )res.len--;//处理头为长度,且保证长度大于等于1

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值