高精算法

对于高精算法其实我很 喜欢,
算法题没事搞这么大数据干嘛,不是为难人吗???
吐槽归吐槽下面我们进入正题。

高精算法的思想,我们由小学列式计算的方法很容易得出
首先我们定义三个数组来储存数据
注意:
以下算法 ~[0]储存高精数位数
数字需使用倒序存储

int sum1[MAXN];//用于计算的高精数1
int sum2[MAXN];//用于计算的高精数2
int result[MAXN];//用于记录答案的高精数

进行计算前别忘了将result初始化,不然可能计算错误哦!
sum1,sum2只需要保证sum[0]相应位数的数字正确即可,其他位是否为零无影响。

#include<cstring>
memset(result,0,sizeof(result));

高精加

高精加低精

void add1(int *sum1,int sum2,int *result)
{
	int i;
	for (i = 1; i <= sum1[0]; i++)
	{
		result[i] = sum1[i];
	}
	result[1] += sum2;
	result[0] = sum1[0];
	for (i = 1; i <= result[0]; i++) //对每一位进行处理,使其大小位于0~9
	{
		result[i + 1] += result[i] / 10;
		result[i] %= 10;
		if (i == result[0]) //达到初始位最高长度后,后一位若不为零,位长度加一,继续处理
			if(result[i+1]>0)
				result[0] += 1;
	}
}

高精加高精

void add2(int *sum1,int *sum2,int *result)
{
	int i;
	int max_len,min_len;
	min_len = sum1[0] < sum2[0] ? sum1[0] : sum2[0];
	max_len = sum1[0] > sum2[0] ? sum1[0] : sum2[0];
	for (i = 1; i <= min_len; i++)//先将每一位相加再进行处理
	{
		result[i] = sum1[i] + sum2[i];
	}
	if(sum1[0]>sum2[0])
		for (i = min_len+1; i <= max_len; i++)
		{
			result[i] = sum1[i];
		}
	else
		for (i = min_len+1; i <= max_len; i++)
		{
			result[i] = sum2[i];
		}
	result[0] = max_len;
	for (i = 1; i <= result[0]; i++)//原理与上面相同
	{
		result[i + 1] += result[i] / 10;
		result[i] %= 10;
		if (i == result[0])
			if(result[i+1]>0)
				result[0] += 1;
	}
}

高精减

注意要使sum1>sum2

高精减低精

void sub1(int* sum1, int sum2, int* result)
{
	int i,j;
	for (i = 1; i <= sum1[0]; i++)
	{
		result[i] = sum1[i];
	}
	result[1] -= sum2;
	result[0] = sum1[0];
	for (i = 1; i <= result[0]; i++)
	{
		if (result[i] < 0) //对每一位进行处理,使其大小位于0~9
		{
			result[i + 1] -= (result[i] + 1) / (-10) + 1;
			if (result[i] % 10 != 0)
				result[i] = result[i] % 10 + 10;
			else 
				result[i] = 0;
		}			
	}
	for (i = result[0]; i >= 2; i--) //最高位长判断
		if (result[i] == 0)
		{
			result[0] --;
		}
		else
			break;
}

高精减高精

void sub2(int* sum1, int* sum2, int* result)
{
	int i,j;
	for (i = 1; i <= sum2[0]; i++) //先将每一位相减再进行处理
	{
		result[i] = sum1[i] - sum2[i];
	}
	for (i = sum2[0]+1; i <= sum1[0]; i++)
	{
		result[i] = sum1[i];
	}
	result[0] = sum1[0];	
	////原理与上面相同
	for (i = 1; i <= result[0]; i++)
	{
		if (result[i] < 0)
		{
			result[i + 1] -= (result[i] + 1) / (-10) + 1;
			if (result[i] % 10 != 0)
				result[i] = result[i] % 10 + 10;
			else 
				result[i] = 0;
		}			
	}
	for (i = result[0]; i >= 2; i--)
		if (result[i] == 0)
		{
			result[0] --;
		}
		else
			break;
}

高精乘

高精乘低精

void mult1(int *sum1,int sum2,int *result)
{
	int i;
	for (i = 1; i <= sum1[0]; i++)//将sum1每一位与sum2相乘,之后进行处理
	{
		result[i] = sum1[i]*sum2;
	}
	result[0] = sum1[0];
	for (i = 1; i <= result[0]; i++)//处理原理与高精加一致
	{
		result[i + 1] += result[i] / 10;
		result[i] %= 10;
		if (i == result[0])
			if(result[i+1]>0)
				result[0] += 1;
	}
}

高精乘高精

void mult2(int* sum1, int* sum2, int* result)
{
	int i,j;
	for (i = 1; i <= sum1[0]; i++)//参考一下小学的列示计算???
	{
		for (j = 1; j <= sum2[0]; j++)
		result[j+i-1] += sum1[i] * sum2[j];
	}
	result[0] = sum1[0] < sum2[0] ? sum1[0] : sum2[0];
	for (i = 1; i <= result[0]; i++)
	{
		result[i + 1] += result[i] / 10;
		result[i] %= 10;
		if (i == result[0])
			if (result[i + 1] > 0)
				result[0] += 1;
	}
}

高精除

高精除低精

void div1(int* sum1, int sum2, int* result)
{
	int i;
	for (i = sum1[0]; i >= 2; i--)//根据小学列式相除而来
	{
		result[i - 1] = (sum1[i] + result[i]) % sum2 * 10;//使result[i - 1]中保存上一位的余数
								//与sum1[i-1]相加便可得目前所处位的被除数
		result[i] = (sum1[i] + result[i])/sum2;//保存相除结果		
	}
	result[1] = (sum1[1] + result[1]) / sum2;
	result[0] = sum1[0];
	for (i = result[0]; i >= 2; i--)//最高位判断
		if (result[i] == 0)
		{
			result[0] --;
		}
		else
			break;
}

高精除高精

写这个代码的时候调bug调了好久。。。。
思想还是挺简单的

void sumCpy(int* sum2, int* divSum, int place)//用于对除法进行减法模拟,
                                              //对于除数按照其相对应的位进行扩大,储存在divSum中
{
	int i;	
	for (i = place; i < place + sum2[0]; i++)
	{
		divSum[i] = sum2[i - place + 1];
	}
	divSum[0] = place + sum2[0] - 1;
}

int sumCmp(int* sum1, int* sum2)//对 divSum 与 原数字被减后剩余的数字 进行比较的算法
                                //从高位到地位对比
{
	int i;
	if (sum1[0] > sum2[0])
	{	
		return 1;
	}
	else
		if (sum1[0] == sum2[0])
		{			
			for (i = sum1[0]; i >= 2; i--)
				if (sum1[i] > sum2[i])
					return 1;
				else
					if(sum1[i] < sum2[i])
						return 0;
			if (sum1[1] >= sum2[1])
				return 1;
		}
	return 0;
}

void sub2(int* sum1, int* sum2, int* result)//前面写过的高精减高精算法,用于减法计算
{
	int i, j;
	for (i = 1; i <= sum2[0]; i++)
	{
		result[i] = sum1[i] - sum2[i];
	}
	for (i = sum2[0] + 1; i <= sum1[0]; i++)
	{
		result[i] = sum1[i];
	}
	result[0] = sum1[0];
	for (i = 1; i <= result[0]; i++)
	{
		if (result[i] < 0)
		{
			result[i + 1] -= (result[i] + 1) / (-10) + 1;
			if (result[i] % 10 != 0)
				result[i] = result[i] % 10 + 10;
			else
				result[i] = 0;
		}
	}
	for (i = result[0]; i >= 2; i--)
		if (result[i] == 0)
		{
			result[0] --;
		}
		else
			break;
}

void div2(int* sum1, int* sum2, int* result)
{
	int i, j;
	int rem[100];
	int divSum[100];
	void sumCpy(int* sum2, int* divSum, int place);
	int sumCmp(int* sum1, int* sum2);
	void sub2(int* sum1, int* sum2, int* result);
	memset(divSum, 0, sizeof(divSum));
	memset(rem, 0, sizeof(rem));
	for (i = 0; i <= sum1[0]; i++)//将被除数储存到rem中用于计算,rem代表剩余数字大小
	{
		rem[i] = sum1[i];
	}
	for (i = sum1[0]; i >= 1; i--)//主体,从高位到地位进行模拟
	{
		sumCpy(sum2, divSum, i);
		while (sumCmp(rem, divSum))//如果rem>divSum则进行一次减法计算
		{
			sub2(rem, divSum, rem);//观察sub2算法,其实可以将第三个数组写为rem,
						//将结果输出到rem中,省去了再次赋值
			result[i] += 1;//在所处位每进行一次减法计算,该位的sum便加一
		}
	}
	result[0] = sum1[0];
	for (i = result[0]; i >= 2; i--)//最高位判断
		if (result[i] == 0)
		{
			result[0] --;
		}
		else
			break;
}
posted @ 2021-03-11 22:13  ReyHan  阅读(339)  评论(0)    收藏  举报