算法-----高精度算法1(高精度加法,高精度减法)(详解)

news2025/1/21 2:56:23

什么是高精度算法?

高精度的意思就是他得名字----高的精度,简单说就是位数很大,而高精度算法就是将这些高精度数(位数很大在几百几千几万位的数叫高精度数)通过计算机的型式模拟出来结果。

为什么要用高精度算法?

在这里插入图片描述

我们都知道c++中int的最大值是2^31,unsigned int的最大值是2的32次方,最大的unsigned long long可以到18446744073709551615 。double是浮点型的最大类型,他的最大值是1.7 * 10^308。
这些数据类型对于1+1=2或43545*51345=2235818025这些式子来说绰绰有余,但如果是下面的呢----
153169256934561745635416456903465967693845681963457348+13547477864672672675474676754676783587875372274=? 265464562574318759893457913479346x6524632656224562664=?
3466779657942964574257456/432654724567=?..?
这些式子的数和结果都非常大long long 和 double 都存不下,这时就是要用高精度来计算了

高精度加法

1168:大整数加法
P1601 A+B Problem(高精)
因为不能用计算机直接计算,只能靠模拟。
让我们回顾一下小学一年级时学的加法。

在这里插入图片描述
通过这个竖式我们想想是否可以把高精度加法转换成一道让我们模拟加法竖式的模拟题呢?答案是肯定的
带着这个假想我们可以尝试下
首先初始化
注意!!!:因为位数较大所以我们要用字符串或字符数组

const int N=205;    //定义大小 
string s1,s2;    //俩数 
int a[N],b[N],c[N];   //存放俩数及结果数组 

好了第二步-------读入(read)

void read(){
	cin>>s1>>s2;
} 

好读入结束,等下,这么草草就结束了a,b数组怎么办。
所以为了照顾a,b数组,我们需要把俩字符串数转成整数数组的型式。
但真的是顺着存储吗?不对
如果顺着存储就是这样
在这里插入图片描述
本来1257+934的式子竟然变了!而且当你好不容易把他变回去时就会发现如果进位时如123+930数组下标竟然需要负数才能存下那个进位的1了!所以顺着存不行,那试试逆序存呢?
大家可以在草稿纸上试试可以发现,逆着存是可以的,也防止了进位溢出的情况
所以,对于存储s1,s2俩数,应用整数数组逆着存。

void read(){
	cin>>s1>>s2;
	int len1=s1.size(),len2=s2.size();
	for(int i=0;i<len1;i++) a[i]=(s1[len1-i-1]-'0');  //逆序存储。需要字符转整数
	for(int j=0;j<len2;j++) b[j]=(s2[len2-j-1]-'0');
} 

好的终于到模拟部分了
让我们先考虑一下重点
1.考虑进位
2.考虑该进位多少
3.最重要的一点。前导零该怎么办
4.最高位进位
好的一步步来
第一点。因为单个位最大是9,俩9相加才18,进位不可能超1,所以第一部分和第二部分可以同时考虑。如果结果大于10,我们可以将结果-10,或直接不判断直接%10,当然我们也要考虑到当前的i+1位也要+1,所以我们可以用变量来表示这种情况。第三点我们可以从尾开始遍历碰到0就舍去(len-1).如果没碰到就break。第四点我们可以用变量储存模拟完毕后特判下
好分析完毕,代码如下

void count(){
	int jw=0;
	len=max(s1.size(),s2.size());   //c的长度是俩数中的最大值或+1
	for(int i=0;i<len;i++){
		c[i]=a[i]+b[i]+jw;    //求当前结果
		jw=c[i]/10;        //进位数
		c[i]%=10;    //得出当前数
	} 
	if(jw==1){   //处理最高位进位
	len++;
	c[len-1]=1;
	}
	while(c[len-1]==0) len--;    //去前导零
}

等下考虑下0+0的结果 ,是空,不是0吗,原来当len==1时就算是0也不能舍去
修改如下

void count(){
	int jw=0;
	len=max(s1.size(),s2.size());
	for(int i=0;i<len;i++){
		c[i]=a[i]+b[i]+jw;
		jw=c[i]/10;
		c[i]%=10;
	} 
	if(jw==1){
	len++;
	c[len-1]=1;
	}
	while(len>1&&c[len-1]==0) len--;
}

最后到输出部分了,应为开始时是逆序存所以也要逆序输出正所谓负负得正

void print(){
	for(int i=len-1;i>=0;i--) cout<<c[i];
}

最后总代如下

#include<bits/stdc++.h>
using namespace std;
const int N=205;     
string s1,s2;  
int a[N],b[N],c[N];  
int len;
void read(){ //读入
	cin>>s1>>s2;
	int len1=s1.size(),len2=s2.size();
	for(int i=0;i<len1;i++) a[i]=(s1[len1-i-1]-'0');
	for(int j=0;j<len2;j++) b[j]=(s2[len2-j-1]-'0');
} 
void count(){    //模拟竖式
	int jw=0;
	len=max(s1.size(),s2.size());
	for(int i=0;i<len;i++){
		c[i]=a[i]+b[i]+jw;
		jw=c[i]/10;
		c[i]%=10;
	} 
	if(jw==1){
		len++;
		c[len-1]=1;
	}
	while(len>1&&c[len-1]==0) len--;
}
void print(){  //输出
	for(int i=len-1;i>=0;i--) cout<<c[i];
}
int main(){
read();
count();
print();
   return 0;
}

另外用结构体来计算大整数加法也是常见的,这里不做多说明了与上文类似

#include<bits/stdc++.h>
using namespace std;
string str;
struct node{   //定义
	int len,s[205];
	node(){len=0;memset(s,0,sizeof(s));}
};
node a,b,c;
node operator + (const node&a,const node&b){  //重载加法运算符
	node c;
	c.len=max(a.len,b.len);
	for(int i=1;i<=c.len;i++){
		c.s[i]+=a.s[i]+b.s[i];
		c.s[i+1]+=c.s[i]/10;
		c.s[i]%=10;
	}
	if(c.s[c.len+1]) c.len++;
	return c;
}
node read(){   //读入加去前导零
	cin>>str;
	int len=str.size();
    node a;a.len=len;
    for(int i=0;i<len;i++){
    	a.s[len-i]=str[i]-'0';
	}
	while(a.len>1&&a.s[a.len]==0) a.len--;
	return a;
}

void print(node a){//输出
	for(int i=a.len;i>=1;i--) cout<<a.s[i];
}
int main(){

a=read(),b=read();
c=a+b;
print(c);
   return 0;
}

高精度减法

1169:大整数减法
与高精度加法类似也是模拟
初始化+读入

string s1,s2;
int a[205],b[205],c[205];
int len;
void read(){
	cin>>s1>>s2;
	int n=s1.size(),m=s2.size();
	len=max(n,m);
	for(int i=0;i<n;i++){
		a[i]=s1[n-i-1]-'0';
	}
	for(int j=0;j<m;j++){
		b[j]=s2[m-j-1]-'0';
	}
}

模拟竖式。
这里也有两项需考虑
1.借位
2.去前导零
第二步相信你们很轻松就能解决。而第一步也很简单我们正常减,如果c[i]<0,那么需要借位了有加就有减,所以c[i]+=10;c[i+1]–;
代码如下

void less(){
	for(int i=0;i<len;i++){
		c[i]+=a[i]-b[i];
		if(c[i]<0){
			c[i]+=10;
			c[i+1]--;
		}
	}
	while(len>1&&c[len-1]==0) len--;
}

最后逆序输出

void print(){
	for(int i=len-1;i>=0;i--) cout<<c[i];
}

总代码

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int a[205],b[205],c[205];
int len;
void read(){
	cin>>s1>>s2;
	int n=s1.size(),m=s2.size();
	len=max(n,m);
	for(int i=0;i<n;i++){
		a[i]=s1[n-i-1]-'0';
	}
	for(int j=0;j<m;j++){
		b[j]=s2[m-j-1]-'0';
	}
}
void lss(){
	for(int i=0;i<len;i++){
		c[i]+=a[i]-b[i];
		if(c[i]<0){
			c[i]+=10;
			c[i+1]--;
		}
	}
	while(len>1&&c[len-1]==0) len--;
}
void print(){
	for(int i=len-1;i>=0;i--) cout<<c[i];
}
int main(){
read();
lss();
print();
   return 0;
}

这边结构体减法代码就不放了,有兴趣可以自己做下。
总结下来,只要会高精度加法就会高精度减法。

未完待续。。。。。。

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

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

相关文章

【运维测试】移动测试自动化知识总结第1篇:移动端测试介绍(md文档已分享)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论移动测试相关知识。主要知识点包括&#xff1a;移动测试分类及android环境搭建&#xff0c;adb常用命令&#xff0c;appium环境搭建及使用&#xff0c;pytest框架学习&#xff0c;PO模式&#xff0c;数据驱动&#xff0…

力扣精选算法100道——【模板】前缀和(一维)

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com) 目录 &#x1f6a9;了解题意 &#x1f6a9;算法原理 &#x1f388;设定下标为1开始 &#x1f388;取值的范围 &#x1f6a9;实现代码 &#x1f6a9;了解题意 第一行的3和2&#xff0c;3代表行数&#xff0c;2代表q次查询(…

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量&#xff0c;叶节点满足&#xff0c;从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现&#xff0c;当不满足条件时直接返回。 到达叶节点后统计答案&#xff0c;用…

结构体,位段问题

结构体&#xff0c;位段问题 一、结构体二、结构体内存分配问题三、存在内存对齐的原因四、结构体传参问题五、结构体实现位段 一、结构体 1.简单说说结构体是什么?  结构体就是把不同的数据类型整合到一起,组成的一个数据类型!!  2.结构体的创建和初始化 struct Stu {char…

【复现】Supabase后端服务 SQL注入漏洞_48

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 Supabase是什么 Supabase将自己定位为Firebase的开源替代品&#xff0c;提供了一套工具来帮助开发者构建web或移动应用程序。 Sup…

【MySQL探索之旅】MySQL数据库下载及安装教程

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…

1921:【02NOIP普及组】过河卒

1921&#xff1a;【02NOIP普及组】过河卒 【题目描述】 如图&#xff0c;A点有一个过河卒&#xff0c;需要走到目标B点。卒行走的规则&#xff1a;可以向下、或者向右。 同时在棋盘上的任一点有一个对方的马&#xff08;如上图的C点&#xff09;&#xff0c;该马所在的点和所有…

leetcode(双指针)11.盛最多水的容器(C++详细解释)DAY9

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回…

CTFshow web(php命令执行 68-71)

web68 还是那句话&#xff0c;没看到flag在哪&#xff0c;那就优先找到flag位置 这里cvar_dump(scandir("/")); 直接输出根目录的位置&#xff0c;然后查看源代码&#xff0c;发现flag位置为flag.txt 知道flag在根目录下面的flag.txt直接访问就好了 cinclude(/flag…

【C++ 02】类和对象 1:初识类和对象

文章目录 &#x1f308; Ⅰ 面向对象介绍&#x1f308; Ⅱ 类的引入&#x1f308; Ⅲ 类的定义格式1. 声明和定义不分离2. 声明和定义分离 &#x1f308; Ⅳ 类的访问限定符&#x1f308; Ⅴ 类的作用域&#x1f308; Ⅵ 类的实例化&#x1f308; Ⅶ this 指针 &#x1f308; Ⅰ…

17 ABCD数码管显示与动态扫描原理

1. 驱动八位数码管循环点亮 1.1 数码管结构图 数码管有两种结构&#xff0c;共阴极和共阳极&#xff0c;ACX720板上的是共阳极数码管&#xff0c;低电平点亮。 1.2 三位数码管等效电路图 为了节约I/O接口&#xff0c;各个数码管的各段发光管被连在一起&#xff0c;通过sel端…

【c++基础】国王的魔镜

说明 国王有一个魔镜&#xff0c;可以把任何接触镜面的东西变成原来的两倍——只是&#xff0c;因为是镜子嘛&#xff0c;增加的那部分是反的。 比如一条项链&#xff0c;我们用AB来表示&#xff0c;不同的字母表示不同颜色的珍珠。如果把B端接触镜面的话&#xff0c;魔镜会把…

LeetCode.145. 二叉树的后序遍历

题目 145. 二叉树的后序遍历 分析 上篇文章我们讲了前序遍历&#xff0c;这道题目是后序遍历。 首先要知道二叉树的后序遍历是什么&#xff1f;【左 右 根】 然后利用递归的思想&#xff0c;就可以得到这道题的答案&#xff0c;任何的递归都可以采用 栈 的结构来实现&#…

Vulnhub靶机:DC2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC2&#xff08;10.0.2.55&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-2,311/…

如何在 Ubuntu 上安装 ONLYOFFICE 文档 8.0

通过使用社区版&#xff0c;您有能力在您自己的服务器上部署 ONLYOFFICE 文档&#xff0c;从而使在线编辑器与 ​​ONLYOFFICE 协作平台​​​或​​其他热门系统​​进行无缝集成。 ONLYOFFICE 文档是什么 ONLYOFFICE 文档是一款全面的在线办公工具&#xff0c;提供了文本文档…

前端 > JS 笔试题面试考题(21-25)

简述请看下面的代码片段并回答以下问题 &#xff1f; for (var i 0; i< 5; i){var btn document.createElement(button);btn.appendChild(document.createTextNode(Button i));btn.addEventListener(click, function(){ console.log(${i} );});document.body.appendChild…

侧信道攻击是什么

侧信道攻击是什么? 侧信道攻击是一种利用系统的物理实现或实现的特定属性来获取信息的攻击方式。这些攻击利用了系统在执行特定操作时产生的信息泄漏&#xff0c;而不是直接攻击系统的计算或加密算法。侧信道攻击通常利用系统的功耗、电磁辐射、时间延迟等物理特性进行攻击&a…

【运维测试】测试理论+工具总结笔记第1篇:测试理论的主要内容(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论测试理论测试工具相关知识。Python测试理论的主要内容&#xff0c;掌握软件测试的基本流程&#xff0c;知道软件测试的V和W模型的优缺点&#xff0c;掌握测试用例设计的要素&#xff0c;掌握等价类划分法、边界值法、因…

【C语言期末项目-通讯录】-升级可动态申请内存版(手把手详细过程,期末评分A+的项目,答辩辅助神博文,建议三连点赞收藏)

目录 ​编辑 前言&#xff1a; 1.项目功能需求分析 2.文件框架说明 3.程序主框架实现 4.创建联系人结构体类型和通讯录结构体类型 4.1创建通讯录 5.程序功能实现--封装功能函数实现不同功能 5.1通讯录初始化 5.2增加联系人 5.3显示所有联系人的信息 5.4删除指定…

COMSOL方法编辑器中产生随机数(可控制随机种子)

简介 COMSOL二次开发主要在方法编辑器中进行&#xff0c;编程语言为Java。有时需要产生随机数&#xff08;比如随机生成一些球体&#xff09;&#xff0c;方法编辑器中已经存在Math.random()可直接使用。 但是&#xff0c;对于某些特殊情况&#xff0c;我希望每次运行代码产生…