高精度计算

1.求N!(0 ≤ N ≤ 10000)

当N很大时
C、C++中,最大的数据类型long long只有64位: 2^64=18446744073709551616,也不够

解题方法

  1. java能直接算:无限大,直到撑爆计算机内存
import java.util.*;
import java.math.*;
public class Main{
	public static void main(String[] args){
		Scanner input  = new Scanner(System.in);
		while(input.hasNext()){
			int n = input.nextInt();
			BigInteger num = BigInteger.ONE;
			for(int i=1;i<=n;i++)
				num = num.multiply(BigInteger.valueOf(i));
			System.out.println(num);
		}
	}
}
  1. 也可用C++的大数乘法
  2. C++中的万进制:用数组存数。从低位到高位,每四位存到一个数组元素中。

连java也处理不了的大数:hdu1061,n = 10^ 9,求n^n的最后一个数字
n = 10^ 9 :即使java能直接算,也会超时。
方案:
(1)数字太大:取模操作。
(2)计算量太大:用快速幂加速。

void multi(int a[],int n)
{
	//1.先乘进去
	for(int i = 1;i <= a[0];i++)
		a[i] *= n;
	//2.处理进位
	int i;
	for(i = 1;i <= a[0];i++){
		a[i + 1] += a[i] / R;
		a[i] %= R;
	}
	//3.处理高位进位
	while(a[i]){
		a[i + 1] = a[i] / R;//高位进位
		a[i++] %= R;
		a[0]++;
	}
}
int main()
{
	string s;int n;
	while(cin >> n){
		int m = s.length();
		int a[N] = {1,1},j = 1;
		for(int i = 2;i <= n;i++)
			multi(a,i);
		print(a);
	}
	return 0;
}
//输出大数a
void print(int a[])
{
	printf("%d",a[a[0]]);
	//中间的0必须有
	for(int i = a[0] - 1;i >= 1;i--)
		printf("%04d",a[i]);
	cout << endl;
}

2.

高精度数的存储,用字符串读入
void init(int a[])
{
	string s;
	cin>>s;//读入字符串s
	a[0]=s.length();
	//用a[0]计算字符串s的位数
	for(i=1;i<=a[0];i++)
		a[i]=s[a[0]-i]-'0';
		//将数串s转换为数组a,并倒序存储.
}
计算结果位数的确定
  1. 高精度加法: 两数之和的位数最大为较大数的位数加1;
  2. 高精度减法: 两数之差的位数最大为较大数的位数;
  3. 高精度乘法: 两数乘积的位数最大为两个因子的位数和
  4. 阶乘和乘方: 可利用对数运算来确定,2 ^ p的位数为:[log10(2^p)+1]=[p*ln2/ln10]+1
  5. 高精度除法: 两数相除的位数最大为较大数的位数减较小的位数加1
高精度数比较

比较数组a和b的大小关系,若a>b返回1,a<b返回-1,a=b返回0

int compare (int a[],int b[])
{
	if (a[0]>b[0]) return 1;//a的位数大于b则a比b大
	if (a[0]<b[0]) return -1;//a的位数小于b则a比b小
	for(int i=a[0];i>0;i--) //从高位到低位比较
	{ 
		if (a[i]>b[i]) return 1;
		if (a[i]<b[i]) return -1;
	}
	return 0;//各位都相等则两数相等。
}
高精度结果的输出
void print(int a[ ]) //打印输出
{
	int i;
	if (a[0]==0){
		cout<<0<<endl;return;
	}
	for(i=a[0];i>0;i--)
		cout<<a[i];
	cout<<endl;
	return ;
}

3.高精度加法

模拟手算
10进制

void jia(int a[],int b[]) //计算a=a+b
{ 
	int i,k;
	if(a[0]<b[0])	a[0]=b[0]; //确定加法最大位数
	for(i=1;i<=a[0];i++) 
		a[i]+=b[i]; //逐位相加
	for(i=1;i<=a[0];i++) //处理进位
	{ 
		a[i+1]+=a[i]/10;
		a[i]%=10;
	}
	if(a[a[0]+1]>0) a[0]++;
	//修正新的a的位数(a+b最多只能的一个进位)
}

N进制运算
1、当前位规范由%10改为% n
2、进位处理由/10改为/n
3、其他运算规则不变

4.高精度减法

void jian(int a[],int b[])//计算a=a-b
{
	int flag,i;
	flag=compare(a,b); //调用比较函数判断大小
	if (flag==0) {
		a[0]=0;
		return;
	}
	//相等
	for(i=1;i<=a[0];i++) {
		if(a[i]<b[i]){
			a[i+1]--;
			a[i]+=10;
		} //若不够减则向上借一位
		a[i]=a[i]-b[i];
	}
	while(a[a[0]]==0) 
		a[0]--; //修正a的位数
	return;
}

5.乘法运算

高精度数组a乘整数i
int chengshu(int a[],int k) //a=a*k,k是单精度数
{ 
	int i;
	if(k==0){
		for(i=0;i<=101;i++)
			a[i]=0;
		a[0]=0;
		return 0;
	} //处理k=0
	for(i=1;i<=a[0];i++)
		a[i]=a[i]*k;//先每位乘起来
	for(i=1;i<=a[0];i++) //处理进位
	{
		a[i+1]+=a[i]/10;
		a[i]%=10;
	}
	while(a[a[0]+1]>0)//处理最高位相乘的进位
	{ 
		a[0]++;
		a[a[0]+1]=a[a[0]]/10;
		a[a[0]]=a[a[0]]%10;
	}
	return 0;
}
两个高精度数组相乘
#include<iostream>
using namespace std;
int a[101]={0},b[101]={0},c[101]={0};
void init(int a[])
{ 
	int i;
	string s;
	cin>>s;
	a[0]=s.length();
	for(i=1;i<=a[0];i++)
		a[i]=s[a[0]-i]-'0';
}
void print(int a[])
{
	int i;
	if (a[0]==0){
		cout<<0<<endl;
		return;
	}
	for(i=a[0];i>0;i--) 
		cout<<a[i];
	cout<<endl;
	return ;
}
void cheng (int a[],int b[],int c[])
{ 
	int i,j,len;
	for (i=1;i<=a[0];i++)
		for (j=1;j<=b[0];j++)
			c[i+j-1]+=a[i]*b[j];
	c[0]=a[0]+b[0];
	for(i=1;i<=c[0];i++)
	{
		c[i+1]+=c[i]/10;
		c[i]%=10;
	}
	while(c[0]>0&&c[c[0]]==0)
		c[0]--;
	return ;
}
int main()
{
	init(a);init(b);
	cheng(a,b,c);
	print(c);
	return 0;
}

6.除法运算

整数数组除以整数(a←a/b,a为整数数组,b为整数)
void chushu(int a[],int b,int c[],int d)//c=a/b,d=a%b
{ 
	int i;
	d=0; //余数初始化
	for(i=a[0];i>=1;i--)//按照由高位到底位的顺序,逐位相除
	{
		d=d*10+a[i]; //接受了来自第i+1位的余数
		c[i]=d/b; //计算商的第i位
		d=d%b;//计算第i位的余数
	}
	c[0]=a[0];
	while(c[0]>0&&c[c[0]]==0)
		c[0]--;//计算商的有效位数
	return ;
}
高精度除法x←x/y(被除数x和除数y为整数)
void chu(int a[],int b[],int c[])
{
	int i,j,tmp[101];
	c[0]=a[0]-b[0]+1;
	for (i=c[0];i>0;i--)
	{
		memset(tmp,0,sizeof(tmp));//数组清零
		numcpy(b,tmp,i); //将b拷贝到tmp的第i位,其余位是0
		while(compare(a,tmp)>=0){c[i]++;jian(a,tmp);}
		//用减法来模拟
	}
	while(c[0]>0&&c[c[0]]==0)
		c[0]--;
	return ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值