高精度的乘除法(C++实现)

news2024/10/6 1:47:28

前言:我们都熟知高精度的加减法可以用字符串来模拟实现,其实乘除法的高精度计算也和加减法类似却也略有不同,下面我们一起来看一下高精度的乘除法的模拟实现,希望可以帮助到大家。

目录

1.高精度乘法的实现

1.1原理重点难点解析

1.2代码实现

2.高精度除法的实现

2.1原理思路描述

2.2 代码实现

3.金句省身 


1.高精度乘法的实现

1.1原理重点难点解析

 原理上并不难,主要还是要注意代码实现的细节问题:

1.2代码实现

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
ll maxsize = 0;//用于记录最长的乘积位数
vector<vector<int>> mul(vector<int>& A, vector<int>& B)
{
	vector<vector<int>>ans;
	for (int i = 0; i < B.size(); i++)
	{
		vector<int> temp;
		for (int k = 0; k < i; k++)
			temp.push_back(0);
		int jinwei = 0;
		for (int j = 0; j < A.size(); j++)
		{
			jinwei += A[j] * B[i];
			temp.push_back(jinwei % 10);
			jinwei /= 10;
		}
		if (jinwei)
			temp.push_back(jinwei);
		ans.push_back(temp);
		maxsize = max(maxsize, (ll)temp.size());
		/*for (int l = temp.size()-1; l>=0; l--)
			cout << temp[l] << " ";
		cout << endl;
		*/
		temp.clear();
	}
	return ans;
}
vector<int> add(vector<vector<int>>& ans)
{
	vector<int> cot;
	int jinwei = 0;
	for (ll j = 0; j < maxsize||jinwei; j++)//最后一次进位有效时仍旧可以进入循环
	{
		for (int i = 0; i < ans.size(); i++)
		{
			if (j < ans[i].size())
				jinwei += ans[i][j];
		}
		cot.push_back(jinwei % 10);
		jinwei /= 10;
	}
	return cot;
}
int main()
{
	string s1, s2;
	cin >> s1 >> s2;
	if(s1=="0"||s2=="0")
	{
	    cout<<"0"<<endl;
	    return 0;
	}
	vector<int>a, b;
	for (int i = s1.size()-1; i >= 0; i--)
		a.push_back(s1[i] - '0');
	for (int i = s2.size()-1; i >= 0; i--)
		b.push_back(s2[i] - '0');
	auto c = mul(a, b);
	auto ans = add(c);
	for (int i = ans.size()-1; i>=0; i--)
		cout << ans[i];//结果为倒序输出的形式
	cout << endl;

	return 0;
}

2.高精度除法的实现

2.1原理思路描述

首先,我们这里应该是以高精度除高精度为条件,高精度除低精度的可以通过“弯道”超车,这里我们不予以讨论,只是以高精度除高精度为前提下的实现方式。

1.我们可以用循环减法模拟实现除法的商的计算,当我们的被减数减去减数还大于减数时,我们就可以让我们的该位上的商加1,直到该位上对应的被减数比减数小了,循环就停下来,此时的变量的累加值就是该位对应的商的结果。

 

2.在存储数组的时候是采取逆序还是正序存储呢,这里我用的是逆序存储,两者的区别在于,逆序存储时方便减法的计算,正序存储时方便除法的计算,其实除法的计算也包括了减法的计算,所以还是让减法运算更方便为好。

减法操作函数

3.如果我们的输入出现被除数比除数小的情况怎么办?

这个时候我们可以将其当做特殊情况进行处理即可,因为这种情况返回的结果不想要计算,直接返回被除数就好,商就是0了。

 

 剩下的就没什么难点了,重点是有很多的细节问题,我们在可以在心里模拟这个过程,包括移位啊,将被除数的下一位落下来等操作,都体现在代码中了,我也是改了很久并用一些注释标出加以解释,希望可以帮助你更好的理解高精度除法的相关实现及其细节问题。

2.2 代码实现

#include <bits/stdc++.h>

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) //减法函数,模拟进行除法商的计算,倒序存储数字也是为了方便进行减法计算
{
	vector<int> C;
	int t = 0;
	for (int i = 0; i < A.size() || t; i++) {
		t = A[i] - t;
		if (i < B.size()) t -= B[i];
		C.push_back((t + 10) % 10);//加10起到了t小于0时可以进行进位操作
		if (t < 0) t = 1;
		else t = 0;
	}
	while (C.size() > 1 && C.back() == 0) C.pop_back();//去除前导0
	return C;
}

vector<int> div(vector<int>& A, vector<int>& B, vector<int>& r) 
{
	vector<int> C; //存储的是倒序的商数组
	//如果被除数比除数还小,那么直接返回0和被除数即可
	if (A.size() < B.size())
	{
		r = A;//一定注意余数是A不是B
		reverse(r.begin(), r.end());
		C.push_back(0);
		return C;
	}
	//注意我们的r数组此时一直处于倒序的状态
	int j = B.size();
	r.assign(max(A.begin(),A.end() - j), A.end());//有可能也会是小数除大数
	while (j <= A.size()) 
	{
		int k = 0;
		while (cmp(r, B))
		{
			vector<int> s = sub(r, B); //减法模拟除法
			r.clear();
			r.assign(s.begin(), s.end());//注意此时r数组还是倒序的
			k++;
		}
		C.push_back(k);//将商放入数组
		if (j < A.size()) 
			r.insert(r.begin(), A[A.size() - j - 1]);//再往后拿被除数一位和除数相除
		if (r.size() > 1 && r.back() == 0) 
			r.pop_back();//去除前导0,注意此时r数组还是倒序的,高位存储在末尾
		j++;
	}
	//reverse(C.begin(), C.end());
	while (C.size() > 1 && *(C.begin()) == 0) C.erase(C.begin());//去除前导0
	
	return C;
}

int main()
{
	string s1, s2;
	cin >> s1 >> s2;
	vector<int> a, b,r;//r表示余数,c表示商数组
	for (int i = s1.size()-1; i >=0; i--)//将数字逆序存入数组中
		a.push_back(s1[i] - '0');
	for (int i = s2.size()-1; i>=0; i--)
		b.push_back(s2[i] - '0');
	auto c = div(a, b, r);
	for (int i = 0; i < c.size(); i++)
		cout << c[i];
	cout << endl;
	for (int i = r.size()-1; i>=0; i--)
		cout << r[i];
	cout << endl;
	return 0;
}

3.金句省身 

       我永远喜欢那些优秀又谦逊的人,他们明明拥有吊打所有人的能力,却又毫无优越感,对人温和的就像傍晚的风,工作上坚定有主见,与人相处时又温和自谦。

      如果恰好喜欢的人也很优秀,那就狠狠的把自己变得优秀,无限去接近。别去害怕,也别去自卑,而是要尽快让你的能力跟得上你的眼光。当你足够优秀,才能散发光芒,自然有同样优秀的人追着光向你走来。

 

 

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

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

相关文章

一图看懂 pyexcel 模块:提供统一 API用来读写操作 Excel 文件的库, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pyexcel 模块&#xff1a;提供统一 API用来读写操作 Excel 文件的库, 资料整理笔记&#xff08;大全&#xff09; 摘要模块图类关系图模块全展开【pyexcel】统计常量模块1 …

ABAP:自定义搜索帮助:可参考标准函数F4IF_SHLP_EXIT_EXAMPLE

当我们在自定义选择屏幕中&#xff0c; 需要写入我们自定义的搜索帮助的时候&#xff0c;可以通过预定义函数来实现&#xff1a; 实例说明&#xff1a; 第一步&#xff1a;创建搜索帮助SE11分销渠道(Z_VTWEG) 1.选择基本索引帮助&#xff1a; 2.选择参考表&#xff0c;因为这…

Java 基础——HashMap 底层数据结构与源码分析

目录 1.HashMap 简介2.HashMap 底层数据结构2.2.JDK1.8 之前2.3.JDK1.8 及以后 3.常量定义3.1.默认初始化容量3.2.最大容量3.3.负载因子3.4.阈值 4.HashMap 源码分析4.1.构造函数4.2.Node<K, V>4.2.put(K key, V value)流程源码 4.3.get(Object key)流程源码 4.4.resize(…

java使用阿里云oss上传文件

java使用阿里云oss上传文件 1、oss 是什么&#xff1f; OSS是阿里云对象存储服务&#xff08;Object Storage Service&#xff09;的一个简称&#xff0c;它是阿里云提供的海量、安全、低成本、高可靠的云存储服务。 即开即用、无限大空间的存储集群。相较传统建服务器存储而…

逻辑回归模型预测

范例题目&#xff1a; 建立一个逻辑回归模型预测一个学生是否通过研究生入学考试。N表示训练集中学生个数&#xff0c;Score1、Score2、 Score3、 Score4是N维数组&#xff0c;分别表示N个学生研究生初试、专业课复试、英语面试成绩、专业课面试成绩。Admitted是N维{0,1}数组&a…

RabbitMQ编程模型

RabbitMQ基础概念 RabbitMQ是基于AMQP协议开发的一个MQ产品。 虚拟主机 virtual host RabbitMQ出于服务器复用的想法&#xff0c;可以在一个RabbitMQ集群中划分出多个虚拟主机&#xff0c;每一个虚拟主机都有AMQP的全套基础组件&#xff0c;并且可以针对每个虚拟主机进行权…

面向对象(高级)-Annotation注解、单元测试的使用

注解&#xff08;Annotation&#xff09; 注解大纲 注解的使用1.Annotation的理解 - 注解&#xff08;Annotation&#xff09;是从JDK5.0开始引入&#xff0c;以注解名在代码中存在。 - Annotation可以像修饰符一样被使用&#xff0c;可用于修饰包、类、构造器、方法、成员变…

LeetCode:59. 螺旋矩阵 II

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;59. 螺旋矩阵 II 题目描述&#xff1a;给你一个正整数 n &#xff0c…

Python中类属性和类方法

1. 类的结构 1.1 术语 —— 实例 使用面相对象开发&#xff0c;第 1 步 是设计 类使用 类名() 创建对象&#xff0c;创建对象 的动作有两步&#xff1a; (1) 在内存中为对象 分配空间 (2) 调用初始化方法 __init__ 为 对象初始化对象创建后&#xff0c;内存 中就有了一个对象…

【敲敲云】零代码实战,主子表汇总统计—免费的零代码产品

近来很多朋友在使用敲敲云时&#xff0c;不清楚如何使用主子表&#xff0c;及如何在主表中统计子表数据&#xff1b;下面我们就以《订单》表及《订单明细》表来设计一下吧&#xff0c;用到的组件有“设计子表”、“公式”、“汇总”等。 《订单》表展示 总金额 订单明细中“小…

C++ Linux Web Server 面试基础篇-操作系统(三、进程通信)

⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨‍🎓。 如果觉得本文能帮到您,麻烦点个赞👍呗! 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。👍⭐️❤️ Qt5.9专栏定期更新Qt的一些项目Demo 项目与…

恢复调度平台mysql主从同步

修复问题 调度平台两台MySQL从节点存在Slave_SQL_Running异常&#xff0c;需要恢复。 部署步骤 一、先停止调度平台core服务与web服务&#xff0c;否则无法正常锁表 1.1停止调度平台core服务 2.1停止web服务 3.确认MySQL所有执行线程是否都已经停止 show processlist; 如…

小红书流量规则是什么,推荐机制解读

当今的互联网自媒体世界&#xff0c;说到底还是一个流量时代&#xff0c;一个流量为王的时代。不管你在小红书也好&#xff0c;还是其他自媒体平台都需要知晓平台的流量规则。今天和大家分享下小红书流量规则是什么&#xff0c;让我们一起通过流量规则分析小红书机制和算法。 一…

人工智能如何助力建筑设计自动化?

ChatGPT和DALL-E等工具使用大规模机器学习(ML)模型&#xff0c;并访问大量有标记和有意义的数据&#xff0c;以对文本和图像中的查询提供有见解的响应。但是&#xff0c;一些行业对训练ML模型的数据集的访问有限&#xff0c;这使得使用生成式AI来解决现实世界问题的好处很难获得…

书写我的人生回忆录-这应该是给父母最好的礼物

作为一个业余的软件开发爱好者&#xff0c;我又捣鼓了一个有意思的小东西 &#xff0c;使用完全免费哈 《书写我的人生回忆录》是一款软件&#xff0c;其中包含70个问题&#xff0c;涵盖了父母的个人喜好、家庭、工作、人生经历和态度等方面。通过回答这些问题&#xff0c;您的…

爬虫请求头Content-Length的计算方法

重点&#xff1a;使用node.js 环境计算&#xff0c;同时要让计算的数据通过JSON.stringify从对象变成string。 1. Blob size var str 中国 new Blob([str]).size // 6 2、Buffer.byteLength # node > var str 中国 undefined > Buffer.byteLength(str, utf8) 6 原文…

Spring开启事务流程和事务相关配置

文章目录 Spring事务Spring快速入门事务相关配置 Spring事务 Spring快速入门 事务作用&#xff1a;在数据层保障一系列的数据库操作同成功同失败 Spring事务作用&#xff1a;在数据层或业务层保障一系列的数据库操作同成功同失败 Spring提供了一个接口PlatformTransactionMa…

Vue可视化项目搭建

安装Nodejs 全局下载Vue项目脚手架 创建项目 运行项目 项目初始化 安装Nodejs 下载地址&#xff1a;https://nodejs.org/zh-cn/ 下载完成之后一路点击下一个安装 全局下载Vue项目脚手架 进入开始菜单以管理员身份运行命令提示符 输入更换镜像源为淘宝源 npm config s…

java线程屏障CyclicBarrier

CyclicBarrier允许一组线程在达到一个公共的屏障点时相互等待。它在涉及固定大小的线程组、并且这些线程必须相互等待的程序中非常有用&#xff0c;CyclicBarrier可以在等待的线程被释放后被重用。 构造方法 CyclicBarrier(int parties) 创建一个新的屏障并设置将要访问这个…

问卷调查样本量的确定方法

我们在进行问卷调查的时候&#xff0c;问卷的收集数量是重要的流程之一。问卷数量取决于几个因素&#xff0c;包括研究的目的和研究的类型。接下来&#xff0c;我们就聊一聊怎么确定所需的调查问卷数量。 1、确定研究目标。 确定所需问卷数量的第一步是明确研究目标。这一步是…