首页 > 编程语言 >高精度算法(大数的加、减、乘、除)

高精度算法(大数的加、减、乘、除)

时间:2024-03-19 20:02:37浏览次数:33  
标签:lc temp 高精度 int s2 s1 大数 -- 算法

在C/C++中,int占一个机器字长,32位机中则占4个字节,即[-2^31,2^31-1](10的9次方数量级)。不管是32位还是64位机,long long占8个字节,即[-2^63,2^63-1](10的18次方数量级)。

如果超过该数量级,应该使用高精度算法。

1 加

1、将两个加数逆序存储在两个int数组中。(逆序的原因是方便操作和数据对齐,加法计算都是从低位开始操作,逆序的话就把最低位存在a[0]、b[0]这个位置)

2、两个加数的和,它的最大长度是较长的那个加数的长度+1(lc=max(la,lb)+1)。如果和不是最大长度的话,就会有前导0,需要去除。

3、核心算法:

        c[i]+=a[i]+b[i];
        c[i+1]=c[i]/10;
        c[i]=c[i]%10;

#include<iostream>
#include<string>
using namespace std;
const int N=100;//大数的长度
int a[N],b[N],c[N];

void add(string s1,string s2){
	for(int i=0;i<s1.length();i++){
		a[s1.length()-i]=s1[i]-'0';//逆序存储 
	}
	for(int i=0;i<s2.length();i++){
		b[s2.length()-i]=s2[i]-'0';
	}
	int lc=max(s1.length(),s2.length())+1;
	for(int i=1;i<=lc;i++){
		c[i]+=a[i]+b[i];//有进位,所以是+= 
		c[i+1]=c[i]/10;
		c[i]=c[i]%10;
	} 
	while(lc>1&&c[lc]==0) lc--;//去前导0
	for(int i=lc;i>=1;i--){//逆序输出 
		cout<<c[i];
	} 
	cout<<endl;
}
int main(){
	string s1,s2;
	cin>>s1>>s2;
	add(s1,s2);
	return 0;
} 

2 减

1、比较大小,用大的减小的,如果s1大于s2,输出。如果小于,就添一个负号。 

2、将被减数和减数逆序存储在int数组中。(逆序:和前面的加法一样,减法也是从低位开始计算的)

3、计算得到的差,最长长度也只有被减数那么长(lc=la)。如果没有到达最长长度,需要去除前导0

4、核心算法

        if(a[i]<b[i]){

                a[i+1]--;

                a[i]+=10;

        }

        c[i]=a[i]-b[i];

#include<iostream>
#include<string>
using namespace std;
const int N=100;//大数的长度
int a[N],b[N],c[N];
bool cmp(string s1,string s2){
	if(s1.length()!=s2.length()) return s1.length()>s2.length();
	for(int i=0;i<s1.length();i++){
		if(s1[i]!=s2[i]) return s1[i]>s2[2];
	}
	return true;
}
void subtract(string s1,string s2){
	for(int i=0;i<s1.length();i++){
		a[s1.length()-i]=s1[i]-'0';//逆序存储 
	}
	for(int i=0;i<s2.length();i++){
		b[s2.length()-i]=s2[i]-'0';
	}
	int lc=s1.length();
	for(int i=1;i<=lc;i++){
		if(a[i]<b[i]){
			a[i+1]--;
			a[i]+=10;
		}
		c[i]=a[i]-b[i];
	} 
	while(lc>1&&c[lc]==0) lc--;//去前导0
	for(int i=lc;i>=1;i--){//逆序输出 
		cout<<c[i];
	} 
	cout<<endl;
}
int main(){
	string s1,s2;
	cin>>s1>>s2;
	if(cmp(s1,s2)){
		subtract(s1,s2);
	}else{
		cout<<"-";
		subtract(s2,s1);
	}
	return 0;
} 

3 乘

1、逆序存储两个乘数

2、乘积的最长长度为两个乘数的长度之和(lc=la+lb)。

3、a[i]*b[j]位置对应c[i+j-1]位置。核心代码:

                c[i+j-1]+=a[i]*b[j];

                c[i+j]+=c[i+j-1]/10;

                c[i+j-1]%=10;

#include<iostream>
#include<string>
using namespace std;
const int N=100;
int a[N],b[N],c[N];

void multiply(string s1,string s2){
	for(int i=0;i<s1.length();i++){
		a[s1.length()-i] =s1[i]-'0';//逆序存储 
	}
	for(int i=0;i<s2.length();i++){
		b[s2.length()-i] =s2[i]-'0';
	}
	int lc=s1.length()+s2.length();//乘积的最长长度
	for(int i=1;i<=s1.length();i++){
		for(int j=1;j<=s2.length();j++){
			c[i+j-1]+=a[i]*b[j];
			c[i+j]+=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
	} 
	while(lc>1&&c[lc]==0) lc--;
	for(int i=lc;i>=1;i--){
		cout<<c[i];
	}
	cout<<endl;
}
int main(){
	string s1,s2;
	cin>>s1>>s2;
	multiply(s1,s2);
	return 0;
}

4 除

4.1 高精度÷低精度

1、将高精度的被除数存入int数组,不需要逆序存储,因为除法是从高位开始的。

2、商的最长长度为被除数的长度(lc=la,实际上是lc=la-lb+1,但是b不是高精度的不方便求,这里长度放大一些也没关系),如果没有达到,需要去除前导0

3、核心算法

        c[i]=(r*10+a[i])/b;

        r=(r*10+a[i])%b;

#include<iostream>
#include<string>
using namespace std;
const int N=100;
int a[N],c[N];

void divide(string s1,int b,int &r){
	for(int i=0;i<s1.length();i++){
		a[i+1]=s1[i]-'0';//不需要逆序存储 
	}
	int lc=s1.length();
	for(int i=1;i<=lc;i++){
		c[i]=(r*10+a[i])/b;
		r=(r*10+a[i])%b; 
	}
	int x=1;
	while(c[x]==0&&x<lc) x++;//去前导0 
	for(int i=x;i<=lc;i++){
		cout<<c[i];
	}
	cout<<endl; 
}
int main(){
	string s1;
	int b;
	cin>>s1>>b;
	int r=0;
	divide(s1,b,r);
	cout<<"余数为:"<<r<<endl; 
	return 0;
}

4.2 高精度÷高精度

减法模拟除法,因此本质上是减法,所以存储时需要倒序存储。

以下默认被除数大于等于除数,如果小于的话,答案为0,余数为被除数。

1、将被除数和除数倒序存储在int数组中。

2、商的最长长度为lc=la-lb+1

3、减法模拟。核心算法:

        for(int i=lc;i>=1;i--){

                meset(temp,0,sizeof(temp));//temp也是高精度的,将其清空

                高精度除数左移lc-1位,存在temp中

                while(a>=temp){//高精度比较

                        a[i]++;

                        a=a-temp;//高精度减法   最后的余数也就是a

                }

        }

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int N=100;
int a[N],b[N],c[N],temp[N];//temp数组为除数左移之后的值 
bool cmp(string s1,string s2){
	if(s1.length()!=s2.length()) return s1.length()>s2.length();
	for(int i=0;i<s1.length();i++){
		if(s1[i]!=s2[i]) return s1[i]>s2[i];
	}
	return true;
}
//除数左移 
void move(int b[],int temp[],int x){
	for(int i=1;i<=x;i++){
		temp[i]=0;
	}
	for(int i=1;i<=b[0];i++){
		temp[i+x]=b[i];
	}
	temp[0]=b[0]+x; 
} 
bool compare(int a[],int temp[]){
	if(a[0]!=temp[0]) return a[0]>temp[0];
	for(int i=a[0];i>=1;i--){
		if(a[i]!=temp[i]) return a[i]>temp[i];
	}
	return true;
}
//减法 a=a-temp 
void jian(int a[],int temp[]){
	for(int i=1;i<=a[0];i++){
		if(a[i]<temp[i]){
			a[i+1]--;
			a[i]+=10;
		}
		a[i]=a[i]-temp[i];
	}
	while(a[0]>1&&a[a[0]]==0) a[0]--;
}
void divide(string s1,string s2){
	a[0]=s1.length();//用a[0]存储它的长度 
	b[0]=s2.length();
	for(int i=0;i<s1.length();i++){
		a[s1.length()-i]=s1[i]-'0';//逆序存储 
	}
	for(int i=0;i<s2.length();i++){
		b[s2.length()-i]=s2[i]-'0';
	}
	int lc=s1.length()-s2.length()+1;
	for(int i=lc;i>=1;i--){
		memset(temp,0,sizeof(temp));
		move(b,temp,i-1);//将除数左移i-1位 存在temp数组中 
		while(compare(a,temp)){//a>=temp 
			c[i]++;
			jian(a,temp);//a=a-temp
		}
	}
	while(lc>1&&c[lc]==0) lc--;
	for(int i=lc;i>=1;i--){
		cout<<c[i];
	}
	cout<<endl;
	cout<<"余数为:";
	//余数即为改变后的a
	for(int i=a[0];i>=1;i--){
		cout<<a[i];
	} 
	cout<<endl;
}
int main(){
	string s1,s2;
	cin>>s1>>s2;
	divide(s1,s2);
	return 0;
}

标签:lc,temp,高精度,int,s2,s1,大数,--,算法
From: https://blog.csdn.net/m0_73801775/article/details/136823173

相关文章

  • 实现数据结构与算法学习笔记(java)——顺序表顺序栈代码实现
    顺序表实现顺序栈实现......
  • 大数据分析之数据下钻上卷
    声明:本次任务简单所以没有前后端分离去做,因此不需要异步处理(cors)根据Python将数据合并清洗,分析之后,将得到的数据存入数据库,数据库中就是各行业的类别以及数量。前端用java的相关知识利用echarts绘制数据下钻和上卷图前端:<!DOCTYPEhtml><html><head><metacharset="utf-......
  • 直播预约丨《袋鼠云大数据实操指南》No.1:从理论到实践,离线开发全流程解析
    近年来,新质生产力、数据要素及数据资产入表等新兴概念犹如一股强劲的浪潮,持续冲击并革新着企业数字化转型的观念视野,昭示着一个以数据为核心驱动力的新时代正稳步启幕。面对这些引领经济转型的新兴概念,为了更好地服务于客户并提供切实可行的实践指导,自3月20日起,袋鼠云将推出全新......
  • c++学习记录 STL—常用查找算法
    一、算法简介find               //查找元素find_if             //按条件查找元素adjacent_find       //查找相邻重复元素binary_search      //二分查找法count        ......
  • 高精度AI火灾烟雾检测算法,助力打造更加安全的楼宇环境
    一、方案背景近日,南京居民楼火灾事故导致15人死亡的新闻闹得沸沸扬扬,这一事件又激起了大家对楼宇火灾隐患的进一步担忧。事后我们除了思考政府、消防及物业部门应对此事的解决办法,我们还应该思考如何利用现有的技术帮助人们减少此类事情的发生。二、方案概述含有AI智能分析高精......
  • 用 滑动窗口 算法 解决 蓝桥杯子矩阵 的运行超时 问题
    这题如果用暴力算法解决,会用到四个for循环。当数据很大时,会超时,无法通过蓝桥杯。如果掌握了二维滑动窗口,会让时间复杂度减少俩个数量级,很好地解决超时的问题。关于滑动窗口算法,如果读者不会的话,建议去哔站看大佬的讲解视频,笔者也是昨天才学的。如果已经会了滑动窗口算法,......
  • java数据结构与算法刷题-----LeetCode1005. K 次取反后最大化的数组和(这就不是简单题)
    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846卷来卷去,把简单题都卷成中等题了文章目录1.排序后从小到大取负2.hash表从小到大排序,省掉排序(这就是为什......
  • java数据结构与算法刷题-----LeetCode134. 加油站
    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846文章目录1.贪心2.动态规划1.贪心解题思路:时间复杂度O(......
  • 代码随想录算法训练营第五十一天| ● 309.最佳买卖股票时机含冷冻期 ● 714.买卖股
    最佳买卖股票时机含冷冻期  题目链接:309.买卖股票的最佳时机含冷冻期-力扣(LeetCode)思路:本题难点在于如何将冷冻期加入到状态转移方程中,不妨画个图:按理来说,如何我们正处于买入状态,将股票卖出后,应该是冷冻状态,但是这里多加了一个今日卖出状态,就是将今日卖出和卖出状态分开......
  • 算法训练营第10天|栈与队列基础知识总结 LeetCode 232.用栈实现队列 225.用队列实现栈
    栈与队列基础知识总结 首先要明白栈和队列不同的地方在于,栈是先入后出的结构,队列是先入先出的结构。栈的基本操作栈的定义: stack<int>s;入栈元素:intx;s.push(x);出栈元素:s.pop();返回栈顶元素:s.top();判断栈是否为空:s.empty();队列的基本操作:队列和栈的基本......