浅谈高精度算法

高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。

part 1 数据的存放与输出

  • 以字符串的形式读入数字
  • 用数组保存字符串的逐个字符,数组中的第一个用来保存数字的位数(注意代码中数字是倒序储存在数组中,根据具体运算情况来选择是正序还是倒序哦~)
#include <bits/stdc++.h>
 using namespace std;
 int a[1000],b[1000];
 void cun()
 {
 	char a1[1000],b1[1000];
 	cin>>a1>>b1;
 	a[0]=strlen(a1);
 	b[0]=strlen(b1);
 	for(int i=1;i<=b[0];i++)
 	{
 	  a[i]=a1[a[0]-i]-'0';
 	  b[i]=b1[b[0]-i]-'0';
	 }
	 for(int i=0;i<=a[0];i++)
	 {
	   cout<<a[i]<<endl;
	 }
	 for(int i=0;i<=b[0];i++)
	 {
	   cout<<b[i]<<endl;
	 }
 }
 int main()
 {
 	cun();
 	return 0;
 }

part 2 加法运算

  • 使用一个变量c来存储加法运算后的可能得到的最大位数——也就是a1和b1中位数较大的数再加1。比如100+9900=10000,位数可能会进一。
  • 从最低位到最高位依次相加。同时使用一个变量d来记录可能的进位情况,不进位则为0。
void jiafa()
{
   int c,d=0,e,f[1000];
   c=a[0]>b[0]?a[0]+1:b[0]+1;
   for(int i=1;i<=c;i++)
   {
   	 e=b[i]+a[i]+d;//e先存一下各个位上的加数之和再加上进位情况 
   	 f[i]=e%10;//存这一位上最终的数字
   	 d=e/10;
   }
   return;
} 

part 3 减法运算
这里仅介绍两数均为非负整数,且已知被减数大于减数的情况辣辣辣辣别的情况类似,不过需要自己加上相应的判断代码块

  • 使用一个变量c来存储减法运算后的可能得到的最大位数——也就是被减数的位数。比如10-9=1,位数是1位,比被减数小;而20-1=19,位数与被减数相同。所以最大位数是被减数的位数。
  • 从最低位到最高位依次相减。同时使用一个变量d来记录可能的借位情况,不进位则为0,借了一位以后则为-1,加给下面将要计算的一位。
void jianfa()
{
   int c,d=0,e,f[1000];
   c=a[0];//这里默认a是被减数,b是减数 
   for(int i=1;i<=c;i++)
   {
   	 if(a[i]+d>=b[i])
   	 {
   	 	f[i]=a[i]-b[i]+d;
   	 	d=0;
		}
	  else
	  {
	  	f[i]=a[i]+10-b[i]+d;
	  	d=-1;
	  }
   }
   return;
} 

part 4 乘法运算
根据乘法规律,a的第i位与b的第j位相乘,结果保存在第(i+j-1)位。注意进位的考虑哦~

void chengfa()
{
   int c[1000]={0},d;
   for(int i=1;i<=a[0];i++)
   {
   	 for(int j=1;j<=b[0];j++)
   	 {
   	 	c[i+j-1]=a[i]*b[i]+c[i+j-1];//最开始的乘积 
   	 	c[i+j]=c[i+j]+c[i+j-1]/10;//加上了进位 
   	 	c[i+j-1]=c[i+j-1]%10;//这是在这一位上的数字 
		}
   }
   return;
} 

part 5 除法运算

1.高精度数除以低精度数

  • 注意除法是从高位开始的,所以这里输入的时候不用倒序存进数组啦会比较方便哦。
#include <bits/stdc++.h>
 using namespace std;
 	char a[1000]; 
 	int b,c[1000],d,e,f[1000],h;//c是被除数,f是商,h是余数 
 void shuru() 
 {
 	cin>>a>>b;//b为除数 
 	d=strlen(a);//d为位数 
 	e=0;//为了防止输入的数字有前导0
 	if(a[e]=='0')
 	{
 		e++;
	}
	c[0]=d-e;//c[0]存位数 
	for(int i=e;i<=d;i++)
	{
		c[i-e+1]=a[i]-'0';//如果有前导0,那么e此时为1,也就是从a[1]算起;如果没有前导0,那么e=0,从a[0]算起 
	}
 }
 void chufa1()
 {
 	int g=0; 
 	f[0]=c[0];
	for(int i=1;i<=c[0];i++)
	{
		g=g*10+c[i];
		f[i]=g/b;
		g=g%b;//得到余数 
	 } 
	h=g;
 }
 void shuchu()
 {
 	int i=1;
 	while(f[i]==0)//注意这里是while而不是if,因为可能前面几位都是0 
 	{
 		i++;
	 }
    while(i<=f[0])
	{
	   cout<<f[i];
	   i++; 
	}
	cout<<endl<<h<<endl; 
	return;
  } 
 
 int main()
 {
 	shuru();
 	chufa1();
 	shuchu();
 	return 0;
 } 

2.高精度数除以高精度数
具体每一步的步骤都在代码里,也有部分注释。我觉得最好用例子自己试试,看的还是很清楚哒!

#include <bits/stdc++.h>
 using namespace std;
 int a[1000],b[1000],c[1000];//a是被除数后来又用来存余数,b是除数,c是商 
void shuru(int a1[])
 {
 	char d[1000];
 	cin>>d;
 	a1[0]=strlen(d);
 	for(int i=1;i<=a1[0];i++)
 	{
 		a1[i]=d[a1[0]-i]-'0';//倒序存入数组 
	 }
  } 
void yidong(int b1[],int e[],int wei) 
  {
  	for(int i=1;i<=b1[0];i++)
  	{
  		e[i+wei-1]=b1[i];//跟被除数的每一位对齐
	  }
	e[0]=wei+b1[0]-1;//记录位数 
  }
int bijiao(int a1[],int b1[])//这里的1,-1,0都相当于标记,代表大小相等关系
  {
  	if(a1[0]>b1[0]) 
  	  return 1;
  	if(a1[0]<b1[0])
  	 return -1;
  	for(int i=a1[0];i>0;i--)
  	{
  		if(a1[i]>b1[i])
  		 return 1;
  		if(a1[i]<b1[i])
  		 return -1;
	  }
	return 0;
  }
 void jianfa(int a1[],int b1[])
  {
  	int f;
  	f=bijiao(a1,b1);
  	if(f==0)//如果相等的情况
  	{
  		a1[0]=0;
  		return;
	  }
	if(f==1)
	{
	  for(int i=1;i<=a1[0];i++)
	   {
	     if(a1[i]<b1[i])
	    {
	   	 a1[i+1]--;//借位
	   	 a1[i]+=10;//注意哦,是加10
		   }	
		if(a1[i]>=b1[i])
		{
			a1[i]-=b1[i];
		}
       }
		while((a1[a1[0]]==0)&&(a1[0]>0))
		 a[0]--;
		return; 
	  }  
  }
void chufa(int a1[],int b1[],int c1[])
  {
  	int e[1000];
  	c1[0]=a1[0]-b1[0]+1;//确定商的最大位数
	for(int i=c1[0];i>0;i--)//从最高位开始 
	{
		memset(e,0,sizeof(e));//每次都清空 
		yidong(b1,e,i); 
		while(bijiao(a1,e)>=0)
		{
		   c1[i]++;//得到商的每一位的数字 
		   jianfa(a1,e);	
		} 
	 } 
	 while((c1[c1[0]]==0)&&(c1[0]>0))
	 {
	 	c1[0]--;//确定商的位数 
	 }
  }
 void shuchu(int a1[])
 {
 	if(a1[0]==0)
 	{
 		cout<<"0"<<endl;
 		return;
	 }
	for(int i=a1[0];i>0;i--)
	 cout<<a1[i];
	cout<<endl;
	return;
 }
 int main()
 {
 	memset(a,0,sizeof(a));
 	memset(b,0,sizeof(b));
 	memset(c,0,sizeof(c));
 	shuru(a);  
	shuru(b);
 	chufa(a,b,c);
 	shuchu(c);
 	shuchu(a);
 	return 0;
  } 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值