IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【算法基础3】数字太大了怎么办?c/c++里的高精度加减乘除 -> 正文阅读

[C++知识库]【算法基础3】数字太大了怎么办?c/c++里的高精度加减乘除

一、高精度加法

? ? ? ? 主要思想:通过把较大的数按位依次保存在数组里,实现大数的相加。实际操作中为了方便进位,保存时要采用小端法,从个位开始存储,即存储数7654时,a[0]存4,a[1]存5,a[2]存6,a[3]存7,倒序进行存储。定义t保存进位,从个位开始依次相加,最终运算结果的每一位的值都是A[i]+B[i]+t。结果输出时再倒序遍历数组进行输出。

? ? ? ?

????????例题:两个特别大的数A和B求和。

#include<iostream>
#include<vector>
using namespace std;

vector<int> add(vector<int> &A,vector<int> &B){//对数组进行引用不需要拷贝,节省时间
	int t=0;//t中存储进位
	vector<int> C;
	for(int i=0;i<A.size()||i<B.size();i++){
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);//保存相加结果的个位
		t/=10;//t更新为进位
	}
	if(t) C.push_back(1);//最高位还有进位要补1
	return C;
}

int main(){
	string a,b;//先以字符串读入
	vector<int> A,B;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');//实现ASCLL码到数字的转换
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');//必须是单引号,双引号是字符组,不能相减	
	
    auto C=add(A,B);//auto为计算机自己判断类型,也可以写成vector<int>
	
    for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	return 0;
}

????????注1:重点关注几个遍历中的顺序,读入数组是逆序,相加计算是顺序,输出结果是逆序。

? ? ? ? 注2:vector是向量类型,可以容纳许多类型的数据,因此也被称为容器,尖括号内是数据类型,添加元素用类函数push_back(),读取元素类数组可以直接用下标。

二、高精度减法

? ? ? ? 主要思想:存储和输出与大数相加相同,减法运算时定义t存储借位,当A[i]-B[i]-t<0时不够减,借1位加上10,结果存为A[i]-B[i]-t+10的个位,t更新为1;当A[i]-B[i]-t>=0时够减,结果存为A[i]-B[i]-t的个位,t更新为0。输出时还要考虑多余的0,确保不会出现"000"、“001”等情况。

? ? ? ? 例题:两个特别大的数A和B求差。

#include<iostream>
#include<vector>
using namespace std;

bool cmp(vector<int> &A,vector<int> &B){//自定义cmp函数比较A和B的大小
	if(A.size()!=B.size()) return A.size()>B.size();

	for(int i=A.size()-1;i>=0;i--){//【1】
		if(A[i]!=B[i]) return A[i]>B[i];
	}
	return true;//遍历完还没有返回,A=B
}

vector<int> sub(vector<int> &A,vector<int> &B){
	int t=0;//t存储借位
	vector<int> C;

	for(int i=0;i<A.size();i++){
		t=A[i]-t;
		if(i<B.size()) t-=B[i];//当B还没有遍历完才减
		C.push_back((t+10)%10);//合并t>=0和t<0的两种处理情况
		if(t>=0) t=0;//够减,不用借位
		else t=1;//不够减,借位1
	}

	while(C.size()>1&&C.back()==0) C.pop_back();
    //处理冗余的0,C的最后一个值即为结果的最高位
	return C;
}

int main(){
	string a,b;
	vector<int> A,B;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
		
	if(cmp(A,B)){//当A>=B时直接减
		auto C=sub(A,B);
		for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	} 
	else{//A<B时计算B-A再添负号	
		auto C=sub(B,A);
		printf("-");
		for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);//【2】
	}
	
	return 0;
}

? ? ? ? 【1】:A和B位数相同时,比较第一个不相等的数的大小来确定A和B的大小。注意数组内是逆序存储,比较时要从高位依次向后比较,逆序遍历。

????????【2】:虽然不论A-B还是B-A,输出C的方式相同,但只能把输出写在if-else内,写到外面编译器识别不到C的定义会报错。

三、高精度乘法

? ? ? ? 主要思想:按照多位数乘个位数的计算方式,把小数b当成个位数进行乘法运算。从个位开始遍历大数A的每一位A[i],依次与小数b进行乘法运算,最终结果C的每一位C[i]都是每次乘法运算的结果模10,进位是每次乘法运算的结果除以10。

? ? ? ? 例题:求一个很大的数a乘一个很小的数b。

#include<iostream>
#include<vector>
using namespace std;

vector<int> mul(vector<int> &A,int b){
	vector<int> C;
	int t=0;//t存储进位
	for(int i=0;i<A.size()||t;i++){//A中还有数没计算或者进位t不为0
		if(i<A.size()) t+=A[i]*b;//只有A中还有数没计算时才做乘法,注意是+=
		C.push_back(t%10);
		t/=10;//储存进位
	}
	return C;
}

int main(){
	vector<int> A;
	string a;
	int b;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	
	auto C=mul(A,b);
	
	for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	return 0;
}

四、高精度除法

? ? ? ? 主要思想:从大数的最高位开始依次做除法,每次除法商保留除以b的值,进位为余数乘以10。

? ? ? ? 例题:求一个很大的数除以一个小数的商和余数。

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

vector<int> div(vector<int> &A,int b,int &r){//r保存余数
	vector<int> C;
	for(int i=A.size()-1;i>=0;i--){//【1】
		r=r*10+A[i];
		C.push_back(r/b);
		r%=b;//注意进位为模b
	}
	reverse(C.begin(),C.end());//C中的结果是大端存储,逆序方便后面输出
	while(C.size()>1&&C.back()==0) C.pop_back();//此处是pop_back,先逆序再除冗余0

	return C;
}

int main(){
	vector<int> A;
	string a;
	int b;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	
	int r=0;
	auto C=div(A,b,r);
	
	for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	cout<<endl<<r<<endl;
	
	return 0;
}

? ? ? ? 【1】:注意除法运算时是从最高位开始计算,但是为了与加法减法乘法统一,便于综合计算,存储时还是用小端法(即从最低位开始存储),计算时要逆序遍历,C中的结果是大端存储,再调用reverse()函数将结果转成小端存储,便于输出。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:08:17  更:2022-09-21 00:10:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 12:42:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码