基础算法一:C++高精度计算(加,减,乘,除)详解

一、前言:

        有些计算要求精度高,希望计算的数的位数可达数十位或数百位,但因受到硬件的限制,往往很难达到实际问题所要求的精度。

二、在数据的处理中需要的几个要素:

(1)数据的接收方式/存贮方法:

        输入的数很长,则可采用字符串方式输入,这样可输入位数很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组。

void init(int a[])          //传入一个数组
{
  string s;
  cin>>s;                   //读入字符串s
  len=s.length();           //用len计算字符串s的位数
  for(i=1;i<=len;i++)
    a[i]=s[len-i]-'0';      //将字符串s转换为数组a,并倒序储存
}

另一种方法是直接用循环加数组方法输入数据。

(2)高精度位数的确定

位数的确定:接受时往往是用字符串的,所以它的位数就等于字符串的长度。

(3)进位,借位处理(先简单理解)

加法进位:

c[i]=a[i]+b[i];
if(c[i]>=10)//进位条件
{
  c[i]%=10;++c[i+1];//取余和进位
}

减法借位:

if(a[i]

乘法进位:

c[i+j-1]=a[i]*b[j]+x+c[i+j-1];
x=c[i+j-1]/10;
c[i+j-1]%=10;

商与余数处理:

与除数与被除数的位数(精度)情况进行处理。分为(1).高精除以低精 (2).高精除以高精

三、算法

(1)高精度加法,2个正整数求和

#include
#include
#include
using namespace std;
int main()
{
	char ca[100], cb[100];
	int a[100], b[100], c[100], a_len, b_len, c_len, i, x;
	memset(a, 0, sizeof(a));//memset()函数作用是在字符串a中,
	memset(b, 0, sizeof(a));//从第一个存储单位开始,将后面
	memset(c, 0, sizeof(a));//sizeof(a)个空间全部置为'\0',达到初始化字符串的目的。
	gets_s(ca);//低版本可用gets()函数,c++中头文件为#includ
	gets_s(cb);//输入两个相加的数
	a_len = strlen(ca);
	b_len = strlen(cb);
	for (i = 0; i <= a_len - 1; i++)
	{
		a[a_len - i] = ca[i] - '0';//数组ca的字符型整数转化为整形放入数组a中,注意逆序
	}
	for (i = 0; i <= b_len - 1; i++)
	{
		b[b_len - i] = cb[i] - '0';//数组cb的字符型整数转化为整形放入数组b中,注意逆序
	}
	c_len = 1;
	x = 0;
	while (c_len <= a_len || c_len <= b_len)
	{
		c[c_len] = a[c_len] + b[c_len] + x;
		x = c[c_len] / 10;
		c[c_len] %= 10;
		c_len++;
	}
	c[c_len] = x;
	if (c[c_len] == 0)//第一位可能是0或1,如果是0则忽略不输出
		c_len--;
	for (i = c_len; i >= 1; i--)//逆序输出结果
	{
		cout << c[i];
	}
	cout << endl;
	return 0;
}

(2)高精度减法,两个正整数求差。

#include
#include
#include
using namespace std;
int main()
{
	//a-b=c
	char ca[100], cb[100], cc[100];
	int a[100], b[100], c[100], a_len, b_len, c_len, i;
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(a));
	memset(c, 0, sizeof(a));
	cout << "Please input minuend" << endl; gets_s(ca);//输入被减数
	cout << "Please input subtrahend" << endl; gets_s(cb);//输入减数
	a_len = strlen(ca);
	b_len = strlen(cb);
	if (strlen(ca) < strlen(cb) || (strlen(ca) == strlen(cb) && strcmp(ca, cb) < 0))
		//strcmp()的作用是比较ca和cb,当ca==cb时,返回0;
		//当ca>cb时,返回正整数;ca 1))
	{
		c_len--;//最高位可能位0,此时不输出此位
	}
	for (i = c_len; i >= 1; i--)
	{
		cout << c[i];//输出结果
	}
	cout << endl;
	return 0;
}

(3)高精度乘法,两个正整数的积

先作分析:c数组的求和得:ci=c'i+c''i+c'''i+…由此可见,①ci与a[i]*b[j]有关②与上一位的进位有关③c1位上的单个数字与c1本身求得的数有关.

综上有:c[i+j-1]=a[i]*b[j]+x+c[i+j-1];   x=c[i+j-1]/10;    c[i+j-1]%=10;  看不懂不要紧,在源码中作具体讲解。

基础算法一:C++高精度计算(加,减,乘,除)详解_第1张图片

#include
#include
#include
using namespace std;
int main()
{
	char a1[100], b1[100];
	int a[100], b[100], c[10000], a_len, b_len, c_len, i, j, x;
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(c, 0, sizeof(c));
	cin >> a1;
	cin >> b1;
	a_len = strlen(a1);
	b_len = strlen(b1);
	for (i = 0; i <= a_len - 1; i++)
	{
		a[a_len - i] = a1[i] - '0';//倒序输入到整型数组
	}
	for (i = 0; i <= b_len - 1; i++)
	{
		b[b_len - i] = b1[i] - '0';
	}
	for (i = 1; i <= a_len; i++)
	{
		x = 0;//存放进位
		for (j = 1; j <= b_len; j++)//对乘数的每一位处理,相当于把乘数各位数拆出,一位数与另一个乘数相乘
		{
			c[i + j - 1] = a[i] * b[j] + x + c[i + j - 1];//当前乘积+进位+原数
			x = c[i + j - 1] / 10;
			c[i + j - 1] %= 10;
		}
		c[i + b_len] = x;//处理进位
	}
	c_len = a_len + b_len;
	while (c[c_len] == 0 && c_len > 1)//删除前导0
		c_len--;
	for (i = c_len; i >= 1; i--)
		cout << c[i];//输出结果
	cout << endl;
	return 0;
}

(4)除法,高精除以低精

做除法时,每一次的商都在0~9,每次求得的余数连接以后的若干位得到新的被除数,继续做除法。因此,在做高精度除法时,要涉及到乘法运算和减法运算,还有位移处理。当然,为了程序简洁,可以避免高精度乘法,用0~9次循环减法取代得到的商的值。这里,我们用按位相除法。

#include
#include
#include
using namespace std;
int main()
{
	char a1[100];
	int a[100], c[100], a_len, i, x = 0, c_len, b;
	memset(a, 0, sizeof(a));
	memset(c, 0, sizeof(c));
	gets_s(a1);
	cin >> b;
	a_len = strlen(a1);
	for (i = 0; i <= a_len - 1; i++)
	{
		a[i + 1] = a1[i] - '0';
	}
	for (i = 1; i <= a_len; i++)//按位相除
	{
		c[i] = (x * 10 + a[i]) / b;
		x = (x * 10 + a[i]) % b;
	}
	c_len = 1;
	while (c[c_len] == 0 && c_len < a_len)
	{
		c_len++;//删除前导0
	}
	for (i = c_len; i <= a_len; i++)
	{
		cout << c[i];
	}
	cout << endl;
	return 0;
}

高精除以高精运用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数(由于每一位的数字小于10,所以对于每一位最多进行10次运算)较为复杂,此篇文章就不多做赘述。

你可能感兴趣的:(c++,经验分享,蓝桥杯,其他,算法)