【算法之路】高精度算法(实现加减乘除)

目录

一、高精度概念

二、高精度算法的实现

1、高精度加法(大整数相加)

2、高精度减法(大整数减法)

3、高精度乘法(大整数*小整数)

4、高精度除法(大整数/小整数)


一、高精度概念

高精度算法,是一种处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几百亿的大数字。一般这类数字统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘等运算。对于非常庞大的数字无法在计算机中正常存储。于是,将这个数字拆开成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数

高精度就是说参与运算的数据和运算结果的范围,超出标准数据类型能表示的数据大小范围的运算。此时如果要得到正确的计算结果,就不能依靠普通方法实现了,而要在普通运算原理的基础上,加以辅助算法来实现超大数据的计算。
例如:求两个 500 位的数据相乘的结果,这时就要用到高精度算法了。


二、高精度算法的实现

1、高精度加法(大整数相加)

大整数又称为高精度整数,其含义就是用基本数据类型无法存储其精度的整数。 大整数的存储使用数组即可。

 

思路:

先将大整数倒序存储,然后从左往右相加,这样才算是从低位往高位加,并判断是否有进位,加出来的数取余后尾插到要保存的vector中,这样求出来的数还是逆序的,但是主函数会从后往前读

 AC代码:

#include<iostream>
#include<string>
#include<vector>
using namespace std;//1、高精度加法(大整数加法)
vector<int> add(vector<int>& A, vector<int>& B)
{//如果B更大,因为下面代码都是以第一个形参作为for结束条件,所以要让大的是第一个形参if (A.size() < B.size()) return add(B, A);vector<int> C;int t = 0; //用来判断是否进位//注意这里是逆序的数从前往后加的for (int i = 0; i < A.size(); ++i){//for循环是以大的数来作为循环结束条件的t += A[i];//for循环以A为结束条件,这里不用格外判断if (i < B.size()) t += B[i];//因没以B为结束条件,故这里要格外判断是否可以加C.push_back(t % 10);//加出来的数要的是余数t /= 10; //判断是否有进位}if (t) C.push_back(t);//有可能最后加完还有进位//第二种写法//这种写法不用格外判断最后是否有进位//for (int i = 0, t = 0; i < A.size()||t; ++i)//{//	if (i < A.size()) t += A[i];//因为有t作为条件,故这里要格外判断//	if (i < B.size()) t += B[i];//因没以B为结束条件,故这里要格外判断是否可以加//	C.push_back(t % 10);//加出来的数要的是余数//	t /= 10; //判断是否有进位//}return C;
}int main()
{string a, b;cin >> a >> b;vector<int> A, B;//把字符串逆序存入vector中,方便后续计算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');auto C = add(A, B);for (int i = C.size() - 1; i >= 0; --i) cout << C[i];cout << endl;return 0;
}

2、高精度减法(大整数减法)

思路:

和加法区别在于其一,减法是要借位而不是进位,其二,减法会导致有前导0存在。

什么是前导0?比如124-113,我们存的是421,311,相减时是4-3=1,2-1=1,1-1=0,然后尾插导致C为110,我们最后是逆着读的,即011,(但正常124-113=11),这里011肯定不对,多了一个前导0,故我们最后要把这个前导0去掉变成11,然后逆着读出来就对了

AC代码: 

#include<iostream>
#include<string>
#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)
{//利用cmp函数比较,使大的数一定是A,与for循环代码相符vector<int> C;int t = 0;//判断借位for (int i = 0; i < A.size(); ++i){t = A[i] - t;//每次都会减掉借位if (i < B.size()) t -= B[i];//关于(t+10)%10(t是减出来的数)//t若为正数(但<=9)其=t%10+10%10=t//t若为负数,正好可以借位+10然后取余数即可C.push_back((t + 10) % 10);if (t >= 0) t = 0;else t = 1; //<0肯定有借位了}//因为两个数相减会导致有多余的0出现,故去除前导0//size()>1是因为可能真的相减出现0,这种0不算前导0while (C.size() > 1 && C.back() == 0) C.pop_back();return C;
}int main()
{string a, b;cin >> a >> b;vector<int> A, B;//把字符串逆序存入vector中,方便后续计算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;if (cmp(A, B)) C = sub(A, B); //正数else cout << "-", C = sub(B, A); //负数for (int i = C.size() - 1; i >= 0; --i) cout << C[i];cout << endl;return 0;
}

3、高精度乘法(大整数*小整数)

思路: 

AC代码: 

#include<iostream>
#include<string>
#include<vector>
using namespace std;vector<int> mul(vector<int>& A, int b)
{vector<int> C;for (int i = 0, t = 0; i < A.size() || t; ++i){if (i < A.size()) t += A[i] * b;//加上t是因为上一次可能有乘出来的进位C.push_back(t % 10);t /= 10;//计算进位}//当b是0时,会出现前导0while (C.size() > 1 && C.back() == 0) C.pop_back();return C;
}int main()
{string a;int b;cin >> a >> b;vector<int> A;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) cout << C[i];cout << endl;return 0;
}

4、高精度除法(大整数/小整数)

思路:

 

AC代码:

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;vector<int> div(vector<int>& A, int b, int& r)
{vector<int> C;for (int i = A.size() - 1; i >= 0; --i){r = r * 10 + A[i];C.push_back(r / b);r %= b; //计算余数}//逆置:因为我们是正常求,但最后是倒着读的,且便于去除前导0reverse(C.begin(), C.end());while (C.size() > 1 && C.back() == 0) C.pop_back();return C;
}int main()
{string a;int b;cin >> a >> b;vector<int> A;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) cout << C[i];cout << endl << r << endl;return 0;
}

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

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

相关文章

经典中的经典之字符串

前言&#xff1a;前段时间发烧了&#xff0c;所以耽误了很多事情&#xff0c;一直没有更新&#xff0c;多穿点衣服&#xff0c;感冒不好受。 接下来有时间就会陆续更新一些基础的算法题&#xff0c;题目都很经典&#xff0c;大家可以先尝试着做&#xff0c;再看 解析。 第一…

sql语法大全

1&#xff0c;创建数据库 create database 数据库名字; 2,查看所有的数据库名称 show databases; MySQL服务器已有4个数据库&#xff0c;这些数据库都是MySQL安装时自动创建的。 information_schema 和 performance_schema 数据库分别是 MySQL 服务器的数据字典&#xff08;…

LongAccumulator

原子操作之LongAccumulator 和LongAdder的区别在于&#xff0c;LongAdder是在Cell里面只能做加减操作&#xff0c;不能乘除&#xff0c;而LongAccumulator就可以定义乘除操作。原理和LongAdder都是一样的&#xff0c;一个Base和一个Cells数组。 原文跳转地址

网工内推 | 合资公司网工,CCNP/HCIP认证优先,朝九晚六

01 中企网络通信技术有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、按照工作流程和指引监控网络运行情况和客户连接状况&#xff1b; 2、确保各监控系统能正常运作&#xff1b; 3、快速响应各个网络告警事件&#xff1b; 4、判断出网络故障&#xff0c;按…

RabbitMQ快速入门(简单收发消息)

文章目录 前言一、数据隔离1.用户管理2.virtual host 二、控制台收发1.交换机2.队列3.绑定 三、编程式收发1.依赖和配置2.收发信息 总结 前言 1.了解数据隔离 2.RabbitMQ控制台收发信息 3.SpringBoot整合RabbitMQ收发信息 一、数据隔离 1.用户管理 点击Admin选项卡&#xff0…

2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题是由安全生产模拟考试一点通提供&#xff0c;危险化学品生产单位安全生产管理人员证模拟考试题库是根据危…

JMeter处理接口签名sign

写接口脚本的时候&#xff0c;很多接口涉及到签名&#xff0c;今天介绍下用JMeter编写签名脚本的方法。 举个例子&#xff0c;开启红包接口&#xff0c;请求方式为post POST /v1/api/red/open json请求参数 { "red_id":1, "timestamp":"1667033841…

Epub书籍阅读工具

Epub书籍阅读工具 前言WIndows总结Neat ReaderAquile ReaderWPS Android总结Neat Reader掌阅 前言 Epub文件为电子书文件格式&#xff0c;此格式的电子书相比txt书籍&#xff0c;增加了目录跳转功能&#xff0c;并可以显示图片。本文介绍WIndows和Android端的epub书籍阅读工具…

【Delphi】使用TWebBrowser执行JavaScript命令传入JSON参数执行出错解决方案

目录 一、问题背景&#xff1a; 二、实际示例&#xff1a; 三、解决方案&#xff1a; 1. Delphi 代码&#xff1a; 2. javaScript代码&#xff1a; 一、问题背景&#xff1a; 在用Delphi开发程序&#xff0c;无论是移动端还是PC端&#xff0c;都可以很方便的使用TWebBrows…

网页数据抓取工具推荐:简数采集器

推荐一款好用的网页数据抓取工具&#xff1a;简数采集器&#xff01;&#xff01;&#xff01; 简数采集器不用下载安装软件&#xff0c;直接可以在浏览器上使用&#xff0c;全程云运行&#xff0c;无需挂机&#xff0c;十分方便。 文章数据采集也非常简单&#xff0c;只需输…

进程间通信(管道/消息队列/共享内存/信号量)

目录 一、进程间通信介绍1.1 进程间通信的目的1.2 进程间通信的发展1.3 进程间通信的分类 二、管道2.1 什么是管道&#xff1f;2.2 匿名管道2.3 实现匿名管道通信的代码2.4 用fork来共享管道原理2.5 站在文件描述符角度-深度理解管道2.6 站在内核角度-管道本质2.7 管道读写的规…