【算法】高精度算法:加减乘除(全)

2023-11-04

看的视频在这里。
题目:
加法
减法
乘法
除法:高/低

加法

思想:用数组模拟高精度。
在这里插入图片描述

算法核心:

c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;
c[i]=c[i]%10;

注意:是c[i]+=a[i]+b[i],是累加

例题:求a+b, a、b范围都<=10^500;

注意:
1、将字符串转成数组模拟大数时要将字符转置,这样才方便做加法,因为数学是向右对齐做加法的,而数组是从左到右的。如:
1234+789==1234+0789 对齐相加,而不是1234+7890对齐相加。
转置即向右对齐,这样进位就向左(向小的位置)进位。

2、la-i最大是la,最小是1.故后面的核心算法是从1开始到lc;

代码如下(有注释):

#include<bits/stdc++.h>
using namespace std;
char s1[505],s2[505];
int a[505],b[505],c[505];
int main()
{
	//用数组模拟高精度算法
	
	int la,lb,lc;
	cin>>s1>>s2;
		
	//得知长度 
	la=strlen(s1);
	lb=strlen(s2);
	
	//将字符转为数字,并将字符转置便于计算
	//此时数字是倒过来的,因为数字的加法是从低位向高位相加(向右对齐) 
	for(int i=0;i<la;i++)
	{
		a[la-i]=s1[i]-'0';
	 } 
	 
	for(int i=0;i<lb;i++)
	{
		b[lb-i]=s2[i]-'0';
	}
	
	//最高位数 
	lc=max(la,lb)+1;
	
	//核心步骤 
	for(int i=1;i<=lc;i++) //为什么从1开始?因为上面的la-i最小就是1 
	{
		c[i]+=a[i]+b[i];
		c[i+1]=c[i]/10;
		c[i]=c[i]%10;
	}
	
	//删除前导0 
	if(c[lc]==0&&lc>0) lc--;
	
	for(int i=lc;i>0;i--)
	{
		cout<<c[i];
	}
	
	return 0;
}

减法

算法核心:
1、若a<b,则交换a与b,并在结果处加上负号。

2、如果a[i]<b[i],则需要高位借位。
核心代码:

if(a[i]<b[i])
{
	a[i+1]--;
	a[i]=a[i]+10;
}
c[i]=a[i]-b[i];

高精度减法例题的代码:

#include<bits/stdc++.h>
using namespace std;

bool compare(char s1[],char s2[])//如果s1>=s2,返回true,否则false; 
{
	int u=strlen(s1),v=strlen(s2);
	if(u>v) return true;
	
	if(u!=v) return u>v; //若u>v,则返回了1,否则0,符合题意
	
	//判断u==v的情况 
	for(int i=0;i<u;i++)
	{
		if(s1[i]!=s2[i])   return s1[i]>s2[i];//这里比较的是从第一位开始的数字; 
	} 
	
	//若还能到这里,则两数相等
	return 1; 
}

char s1[100000],s2[100000];
int a[100000],b[100000],c[100000];
int main()
{
	int la,lb,lc,flag=0;
	cin>>s1>>s2;
	
	if(!compare(s1,s2))//若s1<s2,则flag=1,交换两数字
	{
		flag=1;
		char s3[10000];
		strcpy(s3,s1);
		strcpy(s1,s2);
		strcpy(s2,s3);
	 } 
	 
	 //到这里s1>=s2了
	
	la=strlen(s1);
	lb=strlen(s2);
	
	//转化数字并转置,因减法要向右对齐,而转置后向左对齐,正是数组从左到右的顺序 
	for(int i=0;i<la;i++)
	{
		a[la-i]=s1[i]-'0';
	} 
	 
	for(int i=0;i<lb;i++)
	{
		b[lb-i]=s2[i]-'0';
	}
	
	lc=max(la,lb);//做减法不会进位,不必加1
	
	//由上面的减法可知,数组最小从1开始 
	for(int i=1;i<=lc;i++)
	{
		if(a[i]<b[i])
		{
			a[i+1]--;
			a[i]=a[i]+10;
		}
		c[i]=a[i]-b[i];
	}
	
	//删去前导零,因为减法可能有很多零,要用循环 
	while(c[lc]==0&&lc>1)
	{
		lc--;
	}
	
	if(flag==1)  cout<<"-";
	
	//反着输出回来 
	for(int i=lc;i>0;i--)
	{
		cout<<c[i];
	}
	return 0;
}

减法跟加法有许多相似之处。

乘法

一个例子:
在这里插入图片描述
核心算法:

c[i+j-1]=c[i+j-1]+a[i]*b[j];
c[i+j]=c[i+j]+c[i+j-1]/10;
c[i+j-1]=c[i+j-1]%10;

注意,乘法的最大位数是两个乘数之和
但是!
若是有一个乘数是0,则用if删去前导零会有很多0,如:

0*99999999999999=0000000000000

所以还是要用while删除前导0,或者特判

代码如下:

#include<bits/stdc++.h>
using namespace std;
char s1[10000],s2[10000];
int a[10000],b[10000],c[10000];
int main()
{
	int la,lb,lc;
	cin>>s1>>s2;
	
	la=strlen(s1);
	lb=strlen(s2);
	
	for(int i=0;i<la;i++)
	{
		a[la-i]=s1[i]-'0';
	}
	for(int i=0;i<lb;i++)
	{
		b[lb-i]=s2[i]-'0';
	}
	
	//乘法的位数 
	lc=la+lb;
	
	//核心算法
	for(int i=1;i<=la;i++)
	{
		for(int j=1;j<=lb;j++)
		{
			c[i+j-1]+=a[i]*b[j];
			c[i+j]+=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
	 } 
	 
	//本来lc最多只会比答案多1位,用if删去前导0即可
	//但是!要注意,若有一个乘数是0,则会有很多0,则用while稳妥 
	while(c[lc]==0&&lc>1) lc--; 
	for(int i=lc;i>0;i--)
	{
		cout<<c[i];
	}
	
	return 0;
}

重点是找到a[i] b[i]和c[i] 的规律。

除法

高精度除以低精度

例子:
在这里插入图片描述

核心代码:

	for(int i=1;i<=la;i++)
	{
		c[i]=(x*10+a[i])/b;
		x=(x*10+a[i])%b;
	 } 

注意:这里删除前导零的方法是:
若前面有0,lc就加1,输出的时候从lc开始,这样就把前导零跳过了。

整体代码:

#include<bits/stdc++.h>
using namespace std;

char s1[5005];
long long int b,c[5005],x,a[5005],la,lc;
int main()
{
	cin>>s1>>b;
	
	la=strlen(s1);
	
	//将被除数放入数组 
	for(int i=1;i<=la;i++)
	{
		a[i]=s1[i-1]-'0';
	}
	
	//核心算法
	for(int i=1;i<=la;i++)
	{
		c[i]=(x*10+a[i])/b;
		x=(x*10+a[i])%b;
	 } 
	 
	lc=1;
	while(c[lc]==0&&lc<la) lc++;//删除前导零 
	for(int i=lc;i<=la;i++)
	{
		cout<<c[i];
	}
	
	return 0;
}

高精度除以高精度

例子:
在这里插入图片描述

除数是高精度不能逐位试商,因为可能很多都试不出来。故用减法模拟除法

注意:
1、答案的位数lc=la-lb+1;
如,20/4=5,lc是2(左边第一个是1噢)。
2、最高位的商的来源:用高精度减法,能减多少次商就是几。
3、后面位数的商:被除数是把前面余数*10加上后一位,用高精度减法,重复注意2的步骤。

一个例子:531518/123,第3位的商应该是这样求:
531518-123000,可以减几次,该位数就是几。即,除数左移3位,使得被除数与除数位数相同。
减完之后的39518/123,就是39518-12300能进行几次,即,除数左移两位。

此代码会有很多函数,反正就是让我自己写也写不出来…

代码:

#include<bits/stdc++.h>
using namespace std;

char s1[5005],s2[5005];
int a[305],b[305],c[305],tmp[305];//   a/b==c

//输入字符串并将其转置,变成数字的函数 
void init(int *x)
{
	char s[305];
	cin>>s;
	x[0]=strlen(s);
	
	//将字符串倒序转换为数字:因为涉及到了减法 
	for(int i=0;i<x[0];i++)
	{
		x[x[0]-i]=s[i]-'0';
	}
}


//将除数与被除数对齐,用于做减法的函数:如将123变成12300 
void numcpy(int p[],int q[],int n)
{
	for(int i=1;i<=p[0];i++)
	{
		q[i+n-1]=p[i];//将数字往后推,前面就是0了,转过来就是对齐了的123000(例子) 
	}
	q[0]=p[0]+n-1;
}

 
 //比较两个数谁大的函数
 int compare(int a[],int b[])//返回1:a>b;0:a==b;-1:a<b 
 {
 	if(a[0]>b[0])  return 1;
 	if(a[0]<b[0])  return -1;
 	
 	//走到这里就是位数一样,再往前一位一位地比较 
 	for(int i=a[0];i>0;i--)
 	{
 		if(a[i]>b[i])  return 1;
 		if(a[i]<b[i])  return -1;
	 }
	 
	//a==b
	return 0;
  }
  


//相减的函数
void minu(int a[],int b[])
{
	for(int i=1;i<=a[0];i++)
	{
		if(a[i]<b[i])
		{
			a[i+1]--;
			a[i]=a[i]+10;
		}
		//a[i]是结果了 
		a[i]=a[i]-b[i];
		while(a[a[0]]==0&&a[0]>0)  a[0]--;
	}
 } 

//输出答案函数:转置 
void print(int a[])
{
	if(a[0]==0)
	{
		cout<<0;
		return;
	}
	
	for(int i=a[0];i>=1;i--)
	{
		cout<<a[i];
	}
	return;
 } 
 
 
int main()
{	
	init(a);
	init(b);
	
	//因为数组都是从1开始存的,故a[0]等是没有用的,故将数字的位数存入a[0]
	//作用是:控制商的位数 
	c[0]=a[0]-b[0]+1;
		
	//核心代码: 
	for(int i=c[0];i>=1;i--)
	{
		memset(tmp,0,sizeof(tmp));
		numcpy(b,tmp,i);
		
		//以减法做除法的核心代码
		while(compare(a,tmp)>=0)
		{
			c[i]++;
			minu(a,tmp);
		}
		 
	}
	
	//删去前导零
	while(c[c[0]]==0&&c[0]>0)  c[0]--;
	
	
	//输出商 
	print(c);
	cout<<endl;
	//输出余数(a剩下的除不了的就是余数~) 
	print(a); 
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【算法】高精度算法:加减乘除(全) 的相关文章

  • 为什么存在 async 关键字

    浏览 msdn 9 频道视频时 我发现以下未答复的评论 希望有人能解释一下 我不明白 async 关键字的意义 为什么不直接允许 任何时候方法返回任务时都会使用await关键字 就像迭代器一样 可以在任何返回 IEnumerable 的方法
  • 在 VS2017 下使用 Conan 和 CMake 项目进行依赖管理

    我正在尝试使用 CMake 与 VS2017 集成为 C 设置一个开发环境 以便在 Linux x64 下进行编译 为了更好地管理依赖关系 我选择使用 Conan 但我对这个软件还很陌生 我想知道让 VS2017 识别项目依赖关系的最佳方法
  • 分段错误(核心转储)错误

    我的程序编译罚款 但在输入文件时出现 分段错误 核心转储 错误 我没有正确处理 ostream 吗 include
  • System.IO.IOException:由于意外>数据包格式,握手失败?

    有谁知道这意味着什么 System Net WebException 底层连接已关闭 发送时发生意外错误 gt System IO IOException 由于意外 握手失败 数据包格式 在 System Net Security SslS
  • 在 C# 中生成 HMAC-SHA1

    我正在尝试使用 C 来使用 REST API API 创建者提供了以下用于 hmac 创建的伪代码 var key1 sha1 body var key2 key1 SECRET KEY var key3 sha1 key2 var sig
  • 如何尝试/捕获所有异常

    我正在完成由其他人启动的 UWP 应用程序 该应用程序经常崩溃 我总是陷入困境应用程序 at if global System Diagnostics Debugger IsAttached global System Diagnostic
  • (const T v) 在 C 中从来都不是必需的,对吗?

    例如 void func const int i 在这里 const是不必要的 因为所有参数都是按值传递的 包括指针 真的吗 C 中的所有参数确实都是按值传递 这意味着无论您是否包含该参数 实际参数都不会改变const or not 然而
  • SFINAE 如何使用省略号?

    过去 当使用 SFINAE 选择构造函数重载时 我通常使用以下内容 template
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 两种类型的回发事件

    1 我发现了两篇文章 每篇文章对两种类型的回发事件的分类都略有不同 一位资源说两种类型的回发事件是Changed事件 其中控件实现 IPostbackDataHandler 当数据在回发之间更改时触发 然后Raised事件 其中控件实现 I
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 默认析构函数做了多少事情

    C 类中的默认析构函数是否会自动删除代码中未显式分配的成员 例如 class C public C int arr 100 int main void C myC new C delete myC return 0 删除 myC 会自动释放
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • 在 C++17 中使用 成员的链接错误

    我在 Ubuntu 16 04 上使用 gcc 7 2 并且需要使用 C 17 中的新文件系统库 尽管确实有一个名为experimental filesystem的库 但我无法使用它的任何成员 例如 当我尝试编译此文件时 include
  • C语言声明数组没有初始大小

    编写一个程序来操纵温度详细信息 如下所示 输入要计算的天数 主功能 输入摄氏度温度 输入功能 将温度从摄氏度转换为华氏度 独立功能 查找华氏度的平均温度 我怎样才能在没有数组初始大小的情况下制作这个程序 include
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • 类中不允许使用不完整类型,但类模板中允许使用不完整类型

    以下为无效代码 struct foo struct bar bar x error field x has incomplete type struct bar int value 42 int main return foo x valu
  • C++、三元运算符、std::cout

    如何使用 C 用三元运算符编写以下条件 int condition1 condition2 condition3 int double result int or double std cout lt lt condition1 resul
  • 以 UTF8 而不是 UTF16 输出 DataTable XML

    我有一个 DataTable 我正在使用 WriteXML 创建一个 XML 文件 尽管我在以 UTF 16 编码导出它时遇到问题 并且似乎没有明显的方法来更改它 我了解 NET 在字符串内部使用 UTF 16 这是正确的吗 然后 我通过
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • python numpy从坐标序列中计算累计移动距离

    也是从其他程序中学习得到计算距离 position 通过list来存储坐标xy position append x y position np array position 转换成数组 dist arr np concatenate np
  • 基于docker一行命令搭建个人博客wordPress

    前言 作为对技术热爱的一群小伙伴们 技术分享开源社区的贡献都是我们技术人引以为傲的一件事情 不仅如此 技术分享或者记录也是对自己职业成长的记录 更甚者 如果你的技术分享深度不错 并且帮助到别人那么在面试中也是又很大帮助的 今天就给大家谈一下
  • 两条轨迹相似度算法,轨迹相似性度量

    百度地图 百度地图是百度提供的一项网络地图搜索服务 覆盖了国内近400个城市 数千个区县 在百度地图里 用户可以查询街道 商场 楼盘的地理位置 也可以找到离您最近的所有餐馆 学校 银行 公园等等 2010年8月26日 在使用百度地图服务时
  • VS2019环境下C++配置环境/创建动态链接库

    文章目录 前言 一 配置环境 0 准备 1 添加项目表 2 include文件与lib文件的配置 include文件设置 lib文件配置 二 使用已有代码生成动态链接库 前言 最近有一个收尾的项目分到了手里 由于基本没有使用过VS2019所
  • linux内核oops错误码说明,Linux Kernel Oops异常分析

    0 linux内核异常常用分析方法 异常地址是否在0附近 确认是否是空指针解引用问题 异常地址是否在iomem映射区 确认是否是设备访问总线异常问题 如PCI异常导致的地址访问异常 异常地址是否在stack附近 如果相邻 要考虑是否被踩 比
  • 验证尼科彻斯定理

    验证尼科彻斯定理 即 任何一个整数的立方都可以写成一串连续奇数的和 问题分析与算法设计 本题是一个定理 我们先来证明它是成立的 对于任一正整数a 不论a是奇数还是偶数 整数 a a a 1 必然为奇数 构造一个等差数列 数列的首项为 a a
  • SVN迁移至GIT,并附带历史提交记录

    文章目录 SVN代码同步至GIT 背景 准备工作 操作步骤 SVN代码同步至GIT 背景 近年随着信息工程的多元化发展 GIT逐渐取代SVN成为主流的版本管理工具 部门的项目代码也决定迁移至git进行管理 所以就调研了一下具体的实现方案 要
  • linux创建git仓库

    1 安装 yum install y git 2 查看 Git 版本 git version 3 查看有没有git用户 id git 没有用户创建 useradd git 设置密码 passwd git 删除密码 passwd d f gi
  • Tomcat配置远程调试端口

    1 Linxu系统 bin startup sh开始处中增加如下内容 Java代码 declare x CATALINA OPTS server Xdebug Xnoagent Djava compiler NONE Xrunjdwp tr
  • JVM系列-第10章-垃圾回收概述和相关算法

    文章目录 toc 垃圾回收概述 大厂面试题 蚂蚁金服 百度 天猫 滴滴 京东 阿里 字节跳动 什么是垃圾 为什么需要GC 早期垃圾回收 Java 垃圾回收机制 自动内存管理 应该关心哪些区域的回收 垃圾回收相关算法 标记阶段 引用计数算法
  • Python实现选择排序

    选择排序简介 选择排序 Selection sort 是一种简单直观的排序算法 简单来说就是从无序队列里面挑选最小的元素 和无序队列头部元素替换 放到有序队列中 最终全部元素形成一个有序的队列 选择排序原理 首先在未排序序列中找到最小 大
  • tomcat的启动流程及原理

    组件介绍 Tomcat 最重要的是两个组件是 Connector 连接器 和 Container 容器 集装箱 Connector 组件是可以被替换 这样可以提供给服务器设计者更多的选择 因为这个组件是如此重要 不仅跟服务器的设计的本身 而
  • 当我遵循了这 16 条规范写代码,同事只对我说了三个字: 666

    作者 涛姐涛哥 链接 cnblogs com taojietaoge p 11575376 html 如何更规范化编写Java 代码 Many of the happiest people are those who own the lea
  • CTFshow 信息收集 web18

    根据提示 不要着急 休息 休息一会儿 玩101分给你flag 打开是一个小游戏 要么玩到101分 要么直接作弊 查看源代码 发现js文件 里面发现有个score 0 只要它为101就应该能得到flag了吧 ctrl F搜索score在最底下
  • vue 报错error: 'ev' is defined but never used (no-unused-vars)

    我要做的是用vue在网页上显示一个button 报错信息 修改 没有在components中调用
  • MyBatis-plus 提示 Data truncation: Out of range value for column ‘id‘ at row 1

    记录一下MyBatis plus 提示的错误信息 Error updating database Cause com mysql cj jdbc exceptions MysqlDataTruncation Data truncation
  • Tcpdump命令详解

    目录 一 tcpdump作用 二 tcpdump命令选项和捕获主机到主机的数据包 2 1 命令选项 2 2 tcpdump表达式 关于数据类型的关键字 数据传输方向的关键字 协议关键字 其他关键字 2 3 tcpdump捕获方式 编辑 一
  • 概率论与数理统计 (二)计算题和应用题

    概率论一些知识 https blog csdn net zuoyonggang123 article details 79110916 utm medium distribute pc relevant none task blog OPE
  • 写函数,判断用户传入的参数(字符串、列表、元组)长度是否大于5

    def estimateLength data if len data gt 5 print 该参数长度大于5 else print 该参数长度不大于5 str xiao ran list 12 34 56 78 90 tuple 小灰灰
  • 【算法】高精度算法:加减乘除(全)

    看的视频在这里 题目 加法 减法 乘法 除法 高 低 加法 思想 用数组模拟高精度 算法核心 c i a i b i c i 1 c i 10 c i c i 10 注意 是c i a i b i 是累加 例题 求a b a b范围都 lt