算法知识-9-大数的乘法

一、原理

基本概念:
高精度乘法用于处理超出普通数据类型表示范围的大整数乘法运算。
通常使用数组来存储大整数的每一位数字。
乘法原理:
从两个数的最低位开始,逐位相乘,并将结果错位相加。
错位相加:
每一位相乘的结果需要根据其所在的位置进行错位。例如,最低位相乘的结果无需错位,次低位相乘的结果需要向左错位一位,以此类推。
处理进位:
在相加过程中,可能会产生进位,需要进行进位处理。

二、代码详解

1.基础乘法

大致5个步骤
1.把大整数以字符串格式输入
2.反正为整数数组,且注意格式a1[la-1-i]=a[i]-48;
3.乘法过程中要加进位,将每次乘积存到一个数组中,不断错位然后求和,注意求和也会有进位
4.处理可能存在的进位
5.逆序输出

#include<bits/stdc++.h>
using namespace std;
int main(){
	//1.当字符串输入
	char a[1001],b[1001];
	cin>>a>>b;
	//2.转换反转到整数数组
	int la=strlen(a),lb=strlen(b);
	int a1[1001]={},b1[1001]={};
	for(int i=0;i<la;i++){
		a1[la-1-i]=a[i]-48;
	}
	for(int i=0;i<lb;i++){
		b1[lb-1-i]=b[i]-48;
	}
	//3.模拟整数乘法
	int c1[2001]={};
	int x=0;
	for(int i=0;i<lb;i++){
		for(int j=0;j<la;j++){
			c1[j+i]=c1[j+i]+a1[j]*b1[i]+x;
			x=c1[j+i]/10;
			c1[j+i]=c1[j+i]%10;
		}
		c1[i+la]=x;
		x=0;
	}
	//4.最后的进位非0,长度加1
	int lc=la+lb-1;
	if(c1[lc]!=0){
		lc++;
	}
	//5.逆序输出
	for(int i=lc-1;i>=0;i--){
		cout<<c1[i];
	}
	return 0;
} 

大整数乘以小整数

乘法中如果已知会有一个小整数参加运算,那么我们知道大整数中每个数乘以小整数,数字都不会很大,因此我们可以将小整数作为一个整体不断的与每一个大整数相乘,然后再相加求和,从而实现乘积

#include<bits/stdc++.h>
using namespace std;
int main(){
	//1.输入两个整数a,b
	char a[1001]; //大整数
	int b; //小整数
	cin>>a>>b;
	//2.大整数转换反转到整数数组
	int la=strlen(a);
	int a1[1001]={};
	for(int i=0;i<la;i++){
		a1[la-1-i]=a[i]-48;
	}
	//3.数组a1的元素依次乘以b
	int c1[1011]={},x=0; //c1存乘积,x存进位
	for(int i=0;i<la;i++){
		c1[i] = a1[i]*b + x;
		x = c1[i]/10;
		c1[i] = c1[i]%10;
	}
	//4.拆分存储最后的进位
	while(x>0){
		c1[la]=x%10;
		x=x/10;
		la++;
	}
	//5.逆序输出
	for(int i=la-1;i>=0;i--){
		cout<<c1[i];
	}
	return 0;
}

求10000以内n的阶乘

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	//1.准备数组存储累乘
	int c1[50001]={1};
	int lc=1;//结果长度
	//2.遍历小整数1~n
	for(int i=1;i<=n;i++){
		//3.大整数c1乘以小整数i
		int x=0;//进位
		for(int j=0;j<lc;j++){
			c1[j]=c1[j]*i+x;
			x=c1[j]/10;
			c1[j]=c1[j]%10;
		}
		//拆分存储最后的进位
		while(x>0){
			c1[lc]=x%10;
			x=x/10;
			lc++;
		}
		//注意:下标lc未使用,结果逆序从下标lc-1输出
	}
	//4.逆序输出
	for(int i=lc-1;i>=0;i--){
		cout<<c1[i];
	}
	return 0;
}

1计算多组大整数相乘

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin>>t;
	for(int k=1;k<=t;k++){
		//1.当字符串输入
		char a[105],b[105];
		cin>>a>>b;
		int la=strlen(a),lb=strlen(b);
		//2.转换反转到整数数组
		int a1[105]={},b1[105]={};
		for(int i=0;i<la;i++){
			a1[la-1-i]=a[i]-48;
		}
		for(int i=0;i<lb;i++){
			b1[lb-1-i]=b[i]-48;
		}
		//3.模拟整数乘法
		int c1[205]={};
		int x=0;
		for(int i=0;i<lb;i++){//第2个因数
			for(int j=0;j<la;j++){//第1个因数
				c1[j+i]=c1[j+i]+a1[j]*b1[i]+x;
				x=c1[j+i]/10;
				c1[j+i]=c1[j+i]%10;
			}
			c1[i+la]=x;
			x=0;
		}
		//4.最后的进位非0,长度加1
		int lc=la+lb-1;
		if(c1[lc]!=0){
			lc++;
		}
		//5.逆序输出
		for(int i=lc-1;i>=0;i--){
			cout<<c1[i];
		}
		cout<<endl; //换行
	}
	return 0;
}

2先加再乘

#include<bits/stdc++.h>
using namespace std;
char a[205],b[205],c[205]; 
int a1[205]={},b1[205]={},c1[205]={};
int main(){
	//当字符串输入
	cin>>a>>b>>c;
	int la=strlen(a),lb=strlen(b),lc=strlen(c);
	
	//计算(a+b)的和
	for(int i=0;i<la;i++)	a1[la-1-i]=a[i]-48;
	for(int i=0;i<lb;i++)	b1[lb-1-i]=b[i]-48;
	int ld=la>lb?la:lb; //和的长度
	int d1[205]={},x1=0; //d1保存和,x1进位
	for(int i=0;i<ld;i++){
		d1[i]=a1[i]+b1[i]+x1;
		x1=d1[i]/10;
		d1[i]=d1[i]%10;
	}
	if(x1!=0){
		d1[ld]=x1;
		ld++;
	}
	
	for(int i=0;i<lc;i++)	c1[lc-1-i]=c[i]-48;
	//计算d*c的积
	int e1[500]={},x2=0; //保存积,注意数组的大小
	//d1的长度ld,c1的长度lc
	for(int i=0;i<lc;i++){ //第2个因数
		for(int j=0;j<ld;j++){ //第1个因数
			e1[j+i]=e1[j+i]+d1[j]*c1[i]+x2;
			x2=e1[j+i]/10;
			e1[j+i]=e1[j+i]%10;
		}
		e1[i+ld]=x2;
		x2=0;
	}
	
	int le=ld+lc-1;
	if(e1[le]!=0){
		le++;
	}
	
	//逆序输出
	for(int i=le-1;i>=0;i--)
		cout<<e1[i];
	return 0;
}

3阶乘表达式

#include<bits/stdc++.h>
using namespace std;
int main(){
	string str;
	cin>>str;
	int len=str.size();//表达式长度
	
	//提取整数n
	//1、k1存储n最高位下标,k2存储个位下标
	int k1=len-2,k2=len-2; 
	while((str[k1]>='0'&&str[k1]<='9') && k1>=0)
		k1--;
	k1++;
	//2、利用k1~k2计算整数n
	int n=0;
	for(int i=k1;i<=k2;i++)
		n=n*10+(str[i]-48);
	
	//计算1!+2!+...+n!
	int s1[50001]={},ls=0,x1=0; //累加
	int c1[50001]={1},lc=1,x=0;//阶乘
	for(int i=1;i<=n;i++){
		//计算i(1~n)的阶乘
		for(int j=0;j<lc;j++){
			c1[j]=c1[j]*i+x;
			x=c1[j]/10;
			c1[j]=c1[j]%10;
		}
		while(x>0){
			c1[lc]=x%10;
			x=x/10;
			lc++;
		}
		//x2=0;
		
		//1.计算和的长度
		ls=ls>lc?ls:lc;
		//2.将c1的元素对位累加进s1
		for(int k=0;k<ls;k++){
			s1[k]=s1[k]+c1[k]+x1;
			x1=s1[k]/10;
			s1[k]=s1[k]%10;
		}
		//3.处理最后相加的进位
		if(x1!=0){
			s1[ls]=x1;
			ls++;
		}
		x1=0;
	}
	//逆序输出
	for(int i=ls-1;i>=0;i--){
		cout<<s1[i];
	}
	return 0;
}

4两个小数相乘【难点】

本题中小数位数一定相同哈,大家可以自己设想如果小数数位不同的情况

#include<bits/stdc++.h>
using namespace std;
int main(){
	char a[31],b[31]; 
	int a1[31]={},b1[31]={};
	cin>>a>>b;
	int la=strlen(a);
	
	//确定小数点下标
	int index=0;
	for(int i=0;i<la;i++){
		if(a[i]=='.'){
			index=i;
			break;
		}	
	}
	int lx=la-index-1; //小数的长度
	
	//去掉小数点:从index+1开始都向前移动一位
	for(int i=index+1;i<la;i++){
		a[i-1]=a[i];
		b[i-1]=b[i];
	}
	la--; //去掉小数点,长度减1
	
	//转换反转整数数组
	for(int i=0;i<la;i++){
		a1[la-1-i]=a[i]-48;
		b1[la-1-i]=b[i]-48;
	}
	
	//模拟整数乘法
	int c1[51]={};
	int x=0;
	for(int i=0;i<la;i++){//第2个因数
		for(int j=0;j<la;j++){//第1个因数
			c1[j+i]=c1[j+i]+a1[j]*b1[i]+x;
			x=c1[j+i]/10;
			c1[j+i]=c1[j+i]%10;
		}
		c1[i+la]=x;
		x=0;
	}
	int lc=la+la-1;
	if(c1[lc]!=0){
		lc++;
	}
	
	//逆序输出
	for(int i=lc-1;i>=0;i--){
		cout<<c1[i];
		//因数小数位长度lx,积小数位长度lx*2
		if(i==(lx*2))
			cout<<".";
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值