基础-高精度计算

定义

由于C语言的数据类型能存放的数字大小有一定的限制。
如整型int表达范围是( − 2 31 -2^{31} 231~ 2 31 − 1 2^{31}-1 2311)
无符号整数unsigned long是(0~ 2 32 − 1 2^{32}-1 2321)
浮点型double只能提供15~16位的有效数字。
因此,在计算位数超过十几位的数时,不能采用现有的数据类型,只能自己编程计算。
高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字,我们将这个数字拆开,存放在一个数组里作为一个数字,这样的数就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法。
本文只简单介绍最基本的高精度操作。

输入与预处理

我们输入的数字远超long long等c语言基本数据类型的表示范围,因此我们要把输入的数据作为字符类型数组读取进我们的程序里。
此外,为了方便进行计算(对齐个位、方便处理进位),我们还需要把读取进来的数组逆序放进一个int数组里。相应的,输出也应逆序。
代码如下。

#include <stdio.h>
#include <string.h>
struct asdf{
	int n,x[1001];
};
char A[1001];
void change(char *A,asdf *a)
{
	(*a).n=strlen(A);
	for (int i=0;i<(*a).n;++i) 
		(*a).x[(*a).n-i]=A[i]-'0';
}
void Scan(asdf *a)
{
	memset((*a).x,0,sizeof((*a).x));
	scanf("%s",A);
	change(A,a);
}
void Print(asdf a)
{
	for (int i=a.n;i;--i) printf("%d",a.x[i]);
}
int main()
{
	asdf a;
	Scan(&a);
	Print(a);
}

高精加

思想

用竖式计算7685+3419。

流程在这里插入图片描述

代码

#include <stdio.h>
#include <string.h>
struct asdf{
   int n,x[1001];
};
char A[1001];
void change(char *A,asdf *a)
{
   (*a).n=strlen(A);
   for (int i=0;i<(*a).n;++i) 
   	(*a).x[(*a).n-i]=A[i]-'0';
}
void Scan(asdf *a)
{
   memset((*a).x,0,sizeof((*a).x));
   scanf("%s",A);
   change(A,a);
}
void Print(asdf a)
{
   for (int i=a.n;i;--i) printf("%d",a.x[i]);
}
asdf Plus(asdf a,asdf b)
{
   asdf ans;
   ans.n=(a.n>b.n?a.n:b.n); //和的长度不小于任一加数的长度 
   for (int i=1;i<=a.n||i<=b.n;i++) //ans的每一位都等于两加数该位之和加进位 
   	ans.x[i]=a.x[i]+b.x[i]+ans.x[i-1]/10,ans.x[i-1]%=10;
   if (ans.x[ans.n]>10) ans.x[ans.n]%=10,ans.x[++ans.n]=1; 
   return ans;
}
int main()
{
   asdf a,b;
   Scan(&a); //调用输入并预处理函数 
   Scan(&b);
   asdf ans=Plus(a,b); //调用求和函数 
   Print(ans); //调用输出函数 
}

高精减

思想

用竖式计算7685-3419。

流程在这里插入图片描述

代码

#include <stdio.h>
#include <string.h>
struct asdf{
   int n,x[1001],f;
};
char A[1001];
void change(char *A,asdf *a)
{
   (*a).n=strlen(A);
   for (int i=0;i<(*a).n;++i) 
   	(*a).x[(*a).n-i]=A[i]-'0';
}
void Scan(asdf *a)
{
   (*a).f=1;
   memset((*a).x,0,sizeof((*a).x));
   scanf("%s",A);
   change(A,a);
}
void Print(asdf a)
{
   if (a.f<0) printf("-");
   for (int i=a.n;i;--i) printf("%d",a.x[i]);
}
int Compare(asdf a,asdf b)
{
   if (a.n<b.n) return 1;
   if (a.n>b.n) return 0;
   for (int i=1;i<=a.n;++i)
   	if (a.x[i]<b.x[i]) return 1;
   	else if (a.x[i]>b.x[i]) return 0;
   return 0;
}
asdf Minus(asdf a,asdf b)
{
   asdf ans;
   if (Compare(a,b))//如果小数减大数就返回-(b-a) 
   {
   	ans=Minus(b,a);
   	ans.f=-1;
   	return ans;
   }
   ans.n=(a.n>b.n?a.n:b.n);//和的长度不大于被减数的长度 
   for (int i=1;i<=ans.n;++i) ans.x[i]=a.x[i]-b.x[i];
   for (int i=1;i<ans.n;++i)//处理借位 
   	if (ans.x[i]<0) ans.x[i]+=10,ans.x[i+1]--;
   while (ans.x[ans.n]==0&&ans.n>1) ans.n--;//去前导零 
   return ans;
}
int main()
{
   asdf a,b;
   Scan(&a); //调用输入并预处理函数 
   Scan(&b);
   asdf ans=Minus(a,b); //调用求和函数 
   Print(ans); //调用输出函数 
}

高精乘单精

思想

不使用竖式,计算128712*2。

流程在这里插入图片描述

代码

#include <stdio.h>
#include <string.h>
struct asdf{
   int n,x[1001],f;
};
char A[1001];
void change(char *A,asdf *a)
{
   (*a).n=strlen(A);
   for (int i=0;i<(*a).n;++i) 
   	(*a).x[(*a).n-i]=A[i]-'0';
}
void Scan(asdf *a)
{
   (*a).f=1;
   memset((*a).x,0,sizeof((*a).x));
   scanf("%s",A);
   change(A,a);
}
void Print(asdf a)
{
   if (a.f<0) printf("-");
   for (int i=a.n;i;--i) printf("%d",a.x[i]);
}
asdf Times(asdf a,int b)
{
   asdf ans;
   ans.n=a.n;
   int x=0;
   for (int i=1;i<=ans.n;++i)
   {
   	ans.x[i]=a.x[i]*b+x;
   	x=ans.x[i]/10;
   	ans.x[i]%=10;
   }
   while (x) ans.x[++ans.n]=x%10,x/=10;
   return ans;
}
int main()
{
   asdf a;
   int b;
   Scan(&a); //调用输入并预处理函数 
   scanf("%d",&b);
   asdf ans=Times(a,b); //调用求和函数 
   Print(ans); //调用输出函数 
}

高精乘高精

思想

用竖式计算542*768。

流程

在这里插入图片描述

代码

#include <stdio.h>
#include <string.h>
struct asdf{
	int n,x[5001];
};
char A[5001];
void change(char *A,asdf *a)
{
	(*a).n=strlen(A);
	for (int i=0;i<(*a).n;++i) 
		(*a).x[(*a).n-i]=A[i]-'0';
}
void Scan(asdf *a)
{
	memset((*a).x,0,sizeof((*a).x));
	scanf("%s",A);
	change(A,a);
}
void Print(asdf a)
{
	for (int i=a.n;i;--i) printf("%d",a.x[i]);
}
asdf Times(asdf a,asdf b)
{
	asdf ans;
	int x=0;
	memset(ans.x,0,sizeof(ans.x));
	ans.n=a.n+b.n-1; //和的长度不小于两乘数长度之和减一 
	for (int i=1;i<=a.n;++i)
		for (int j=1;j<=b.n;++j) ans.x[i+j-1]+=a.x[i]*b.x[j];
	for (int i=1;i<=ans.n;i++)
		ans.x[i]+=x,x=ans.x[i]/10,ans.x[i]%=10;
	while (x) ans.x[++ans.n]=x%10,x/=10;
	while (ans.x[ans.n]==0&&ans.n>1) ans.n--;
	return ans;
}
int main()
{
	asdf a,b;
	Scan(&a); //调用输入并预处理函数 
	Scan(&b);
	asdf ans=Times(a,b); //调用求和函数 
	Print(ans); //调用输出函数 
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值