【C++算法】——高精度(加,减,乘,除)

前言

高精度算法就是为了去解决一些比较大的数,这些数大到long long都存不下。,这里的主要思想就是用字符串来存。

下面的内容有很多用到c++的容器,不明白的可以先去学习stl。

一  高精度加法

首先第一步就是去模拟我们自己写的加法,,从我们自己写的加法上面来看,第一它是从个位开始加,如果大于10就会产生进位,这个进位要加到下一位去。

我们写加法是从个位开始,但是用代码去写,就需要倒过来,因为个位是不好去进位的,如果用个位去进位,那么就会导致整块的移动,这样效率就会很低了

图一是我们自己算,图二则是我们用代码去实现的过程

所以有了上面的准备,就可以写出下面代码

#include<iostream>
#include<vector>
using namespace std;vector<int> add(const vector<int>& A, const vector<int>& B)//加法函数,这里传引用是为了提高效率
{int t = 0;vector<int>C;//用来返回for (int i = 0; i < A.size(); i++)//因为之前已经逆序了,所以这里直接从0开始遍历{t +=A[i];//首先把最长的数的最后一位加上if (i < B.size()) t += B[i];//因为B短,所以我们需要去判断B是否已经结束C.push_back(t % 10);//最后我们是插入t%10,如果大于就进位,小于就不进位t /= 10;//这里相当于是进位的过程}if (t) C.push_back(1);//还有A结束的时候,可能还有一个进位没有处理,这里把它尾插return C;
}int main()
{string a, b;vector<int>A, B, C;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 (A.size() > B.size()) C = add(A, B);//这里是调整A,B那个数长,长的放上面,比较好操作else C = add(B, A);for (int i = C.size()-1; i >= 0; i--)//因为是逆序相加的,所以这里需要再逆序倒过来输出{cout << C[i];}cout << endl;return 0;}

 主函数里面的处理还是比较简单的,关键在于两个数的相加

二  高精度减法

其实减法也差不多,一样的反转,但是不同的就是我们需要用一个数去存一个借位,而不是进位,因为一个数减另外一个数不够我们就需要去借位,这样才能够减,第二就是我们在进行减法的时候需要的是去判断两个数的大小哪个更加大,而不是和加法一样去判断长度。

一样的,下面看代码理解

bool cmp(vector<int>& A, vector<int>& B)//比较函数
{if (A.size() != B.size())return A.size() > B.size();for (int i = A.size() - 1; i >= 0; i--){if (A[i] != B[i])return A[i] > B[i];}return true;
}vector<int> sub(vector<int>& A, vector<int>& B)//减法函数
{int t = 0;vector<int>C;for (int i = 0; i < A.size(); i++){t = A[i] - t;//一开始没有借位if (i < B.size()) t -= B[i];C.push_back((t + 10) % 10);//这个是如果t>0,说明没有借位,如果小于0,就借位了//这里+10是先算它进位,然后再%10,如果没有进位,那就是它本身//如果进位了,那我们插入的就是10-t;if (t < 0) t = 1;//借位等于1,下次循环,A[i]就需要-1else t = 0;}while (C.size() > 1 && C.back() == 0)C.pop_back();//这里需要去掉前导零return C;
}
int main()
{string a, b;vector<int>A, B, C;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)) C = sub(A, B);//这是判断大小else C = sub(B, A), cout << '-';//如果A小于B,那么我们可以换成-(B-A)//这里要多输出一个符号for (int i = C.size()-1; i >= 0; i--){cout << C[i];}cout << endl;return 0;}

三  高精度乘法

关于高精度乘法来说,就没有减法那么多处理了,甚至比加法还简单一点,这里的乘法是一个多位数和一个低位数的相乘

vector<int> mul(vector<int>& A, int b)
{int t = 0;vector<int>C;for (int i = 0; i < A.size(); i++){t += A[i] * b;//t是进位C.push_back(t % 10);t /= 10;}if (t) C.push_back(t);//最后一位有进位就插入while (C.size() > 1 && C.back() == 0) C.pop_back();//处理前导零return C;
}int main()
{string a;//这里直接正常操作就行int b;vector<int>A, C;cin >> a >> b;for (int i = a.size()-1; i >=0; i--){A.push_back(a[i] - '0');}C = mul(A, b);for (int i = C.size()-1; i >= 0; i--){cout << C[i];}cout << endl;return 0;}

 

四  高精度除法

这里的除法和其他的又有点不一样,但是不一样的不会很多,第一就是我们除一个数可能除不尽,所以这里需要一个余数去存。

vector<int> div(vector<int>& A, int b,int &r)
{r = 0;vector<int>C;for (int i = A.size()-1; i >= 0; i--)//这里和其他的不一样,因为我们除法只能从个位开始除{r = r * 10 + A[i];//这里表示余数和下一个数的相加C.push_back(r / b);r %= b;}reverse(C.begin(), C.end());//这里因为上面的操作把C变为正序了,所以这里要反过来,因为//后面打印是按逆序打印,这里就和上面同一了while (C.size() > 1 && C.back() == 0)C.pop_back();//去前导零return C;
}int main()
{string a;int b;vector<int>A, C;cin >> a >> b;for (int i = a.size()-1; i >=0; i--)//这里操作和上面差不多{A.push_back(a[i] - '0');}int r;C = div(A, b,r);for (int i = C.size()-1; i >= 0; i--){cout << C[i];}cout << endl;cout << r;return 0;}

五 练习

a-b

这里直接用上面的代码就行

 

#include <iostream>
#include <vector>using namespace std;
bool cmp(vector<int>& A, vector<int>& B)//比较函数
{if (A.size() != B.size())return A.size() > B.size();for (int i = A.size() - 1; i >= 0; i--){if (A[i] != B[i])return A[i] > B[i];}return true;
}vector<int> sub(vector<int>& A, vector<int>& B)//减法函数
{int t = 0;vector<int>C;for (int i = 0; i < A.size(); i++){t = A[i] - t;//一开始没有借位if (i < B.size()) t -= B[i];C.push_back((t + 10) % 10);//这个是如果t>0,说明没有借位,如果小于0,就借位了//这里+10是先算它进位,然后再%10,如果没有进位,那就是它本身//如果进位了,那我们插入的就是10-t;if (t < 0) t = 1;//借位等于1,下次循环,A[i]就需要-1else t = 0;}while (C.size() > 1 && C.back() == 0)C.pop_back();//这里需要去掉前导零return C;
}
int main()
{string a, b;vector<int>A, B, C;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)) C = sub(A, B);//这是判断大小else C = sub(B, A), cout << '-';//如果A小于B,那么我们可以换成-(B-A)//这里要多输出一个符号for (int i = C.size()-1; i >= 0; i--){cout << C[i];}cout << endl;return 0;}

a+b

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e6 + 10;
vector<int>add(vector<int>& A, vector<int>& B)
{vector<int>C;int t = 0;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;}if (t)C.push_back(1);return C;}
int main()
{string a, b;cin >> a >> b;vector<int>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');vector<int>C;C = add(A, B);for (int i = C.size() - 1; i >= 0; i--){cout << C[i];}return 0;
}

 

六  总结

以上高精度算法,加法和乘法比较简单,除法和减法需要一点细节理解

加法没有去前导零的操作,其他都有,以上就是高精度的全部内容了,希望对你有所帮助

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nikto一键扫描Web服务器(KALI工具系列三十)

目录 1、KALI LINUX 简介 2、Nikto工具简介 3、信息收集 3.1 目标IP&#xff08;服务器) 3.2kali的IP 4、操作实例 4.1 基本扫描 4.2 扫描特定端口 4.3 保存扫描结果 4.4 指定保存格式 4.5 连接尝试 4.6 仅扫描文件上传 5、总结 1、KALI LINUX 简介 Kali Linux 是一…

2024最新版:C++用Vcpkg搭配VS2022安装matplotlib-cpp库

matplotlib-cpp是一个用于在C中使用matplotlib绘图库的头文件库。它提供了一个简单的接口&#xff0c;使得在C中创建和显示图形变得更加容易。这个库的灵感来自于Python的matplotlib库&#xff0c;它使得在C中进行数据可视化变得更加便捷。 matplotlib-cpp允许在C中使用类似Py…

vue3第五阶段开发文档,后台管理系统

1 5.1 案例——后台管理系统 5.1.1 准备工作 1. 创建项目 打开命令行工具&#xff0c;切换到 D:\vue\chapter05 目录&#xff0c;使用 npm 包管理工具创建一个名称 为 manage-system 的项目&#xff0c;具体命令如下。 npm create vite4.1.0 manage-system -- -…

CTFHUB-SSRF-端口扫描

已经提示我们需要扫描8000~9000的端口 ?urlhttp://127.0.0.1:8000/flag.php 访问用burp抓包爆破 通过Burp扫描8000-9000端口开放的web服务&#xff0c;发现8718开放web服务

QML 列表,图片展示(一)

文章目录 1.QML 列表&#xff0c;图片展示效果图2.项目基本说明3.项目详解3.1界面显示部分3.2 网络部分 4.源代码5.flickr图片查询链接&#xff0c;后面我们将调整代码&#xff0c;获取更多图片 1.QML 列表&#xff0c;图片展示效果图 2.项目基本说明 该项目来自Qt示例程序 Ph…

MySQL数据库(一):数据库介绍与安装

在嵌入式开发中&#xff0c;数据库的重要性体现在高效的数据存储和管理、数据持久化、复杂查询和处理、数据同步和共享、安全性和可扩展性。常见嵌入式数据库包括SQLite、MySQL、LevelDB等&#xff0c;应用于智能家居、工业控制、车载系统和物联网设备&#xff0c;提升了系统功…

关于 pnpm monorepo 项目中 TS2742 Error 的 workaround

最近我在使用 pnpm 作为包管理器开发一个 monorepo 项目&#xff0c;从个人体验来说&#xff0c;在 monorepo 项目中&#xff0c;pnpm 确实要比 yarn classic 用得舒心&#xff0c;最让我欣喜的是 pnpm 对 workspace 协议的支持度很好&#xff1b;另外感受比较明显的一点就是&a…

Nginx+Lua+Redis 实现Nginx301跳转配置管理

业务场景需求 long long ago&#xff1a; 在项目的运维过程中有一次SEO团队提出 网页的URL 中如果可以带上关键字&#xff0c;那么网页在各大搜索引擎中收录和排名有非常重大的突出优势&#xff08;~~SEO团队到底专不专业 ~~&#xff0c;此处不做置评&#xff09;&#xff0c;…

超详细!想进华为od的请疯狂看我!

三分钟带你全面了解华为OD 【合同及管理】签约方为科锐国际/外企德科&#xff08;人力服务公司&#xff09;&#xff0c;劳动合同期为4年&#xff0c;试用期6个月。员工关系合同管理、五险一金、考勤发薪由科锐国际/外企德科负责&#xff1b;定级定薪、员工培训、工作安排、绩…

vuex的配置主要内容

1、state 作用&#xff1a;负责存储数据&#xff1b; 2、getters 作用&#xff1a;state计算属性(有缓存)&#xff1b; 3、mutaions 作用&#xff1a;负责同步更新state数据 mutaions是唯一可以修改state数据的方式&#xff1b; 4、actions 作用&#xff1a;负责异步操作&a…

mysql数据库入门手册

数据库 常见的数据库查看当前用户及其权限创建用户授权用户访问数据库撤销用户权限修改用户密码删除用户增创建一个数据库创建表表中插入数据表中添加字段&#xff08;三种方式&#xff09; 删删除表记录删除表字段删除表&#xff08;三种方式&#xff09;删除数据库 改修改表名…

学生课程信息管理系统

摘 要 目前&#xff0c;随着科学经济的不断发展&#xff0c;高校规模不断扩大&#xff0c;所招收的学生人数越来越 多&#xff1b;所开设的课程也越来越多。随之而来的是高校需要管理更多的事务。对于日益增 长的学生相关专业的课程也在不断增多&#xff0c;高校对其管理具有一…

Linux Kernel入门到精通系列讲解(RV-Kernel 篇) 5.6 在kernel 中实现系统复位和系统关机驱动

1. 概述 上一章节Qemu篇我们已经实现了我们SOC的power reset和 power down 寄存器,本章节我们就在Linux driver中去实现它。 2. Linux kernel 访问其他节点 Linux kernel中有一种机制,就是在driver中访问其它设备树节点的信息,了解设备树的应该都知道,每个设备节点都有一…

【java问答小知识19】一些Java基础的知识,用于想学习Java的小伙伴们建立一些简单的认知以及已经有经验的小伙伴的复习知识点

Java中的"java.util.concurrent.locks.StampedLock"的"tryConvertToReadLock()"方法如何工作&#xff1f; 回答&#xff1a;尝试将当前的写锁转换为读锁&#xff0c;并返回一个表示锁定状态的戳记。 Java中的"java.util.concurrent.locks.StampedLock…

计算机网络:应用层 - 万维网 HTTP协议

计算机网络&#xff1a;应用层 - 万维网 & HTTP协议 万维网 WWW统一资源定位符 URL 超文本传输协议 HTTP非持续连接持续连接非流水线流水线 代理服务器HTTP报文 万维网 WWW 万维网是一个大规模的、联机式的信息储藏所。万维网用链接的方法能非常方便地从互联网上的一个站点…

通信系统网络架构_4.存储网络架构

1.计算机访问磁盘存储有3种方式 一般来说&#xff0c;计算机访问磁盘存储有3种方式&#xff1a; &#xff08;1&#xff09;直连式存储&#xff08;Direct Attached Storage&#xff0c;DAS&#xff09;&#xff1a;计算机通过I/O端口直接访问存储设备的方式。 &#xff08;…

路由

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 客户端&#xff08;例如浏览器&#xff09;把请求发送给 Web 服务器&#xff0c;Web 服务器再把请求发送给 Flask程序实例。程序实例需要知道对每个U…

Kafka 最佳实践:构建高性能、可靠的数据管道

目录 1. 部署最佳实践 1.1 硬件配置 1.2 集群配置 1.3 ZooKeeper 配置 2. 主题和分区设计 2.1 分区设计 2.2 数据保留策略 3. 生产者最佳实践 3.1 生产确认机制 3.2 重试机制 3.3 批量发送 4. 消费者最佳实践 4.1 消费组管理 4.2 并行处理 4.3 错误处理 5. 安全…

昇思25天学习打卡营第5天|网络构建

一、简介&#xff1a; 神经网络模型是由神经网络层和Tensor操作构成的&#xff0c;mindspore.nn提供了常见神经网络层的实现&#xff0c;在MindSpore中&#xff0c;Cell类是构建所有网络的基类&#xff08;这个类和pytorch中的modul类是一样的作用&#xff09;&#xff0c;也是…

std::bind与std::ref配合使用时要注意的几个问题

目录 1 假如输入函数的变量是左值非常量引用&#xff0c;则该变量在std::bind中只能用std::ref修饰&#xff0c;不能用cref&#xff0c;否则编译失败&#xff1a; 2 假如输入函数的变量是左值常量引用&#xff0c;则该变量在std::bind中既可以用std::ref修饰&#xff0c;也可…