大整数运算详解升级版

目录

大整数的存储

大整数的四则运算

高精度加法

高精度减法

高精度与低精度的乘法

高精度与低精度的除法 

大整数的存储

对于大整数使用数组存储,例如定义int型数组d[1000],那么这个数组中的每一位就代表了存放的整数的每一位。如将整数235813存储到数组中,则有d[0]=3,d[1]=1,d[2]=8,d[3]=5,d[4]=3,d[5]=2,即整数的高位存储在数组的高位,整数的低位存储在数组的低位。不反过来存储的原因是,在进行运算的时候都是从整数低位到高位进行枚举,顺位存储和这种思维相和。但是也会由此产生一个需要注意的问题:把整数按照字符串%s读入的时候,实际上是逆位存储的,即str[0]='2',str[1]='3',……,str[5]='3',因此在读入之后需要在另存为d[]数组的时候反转一下。

而为了方便随时获取大整数的长度,一般都会定义一个int型变量len来记录其长度,并和d数组组合成结构体。

struct bign{int d[1000];int len;
};

显然,在定义结构体变量之后,需要马上初始化结构体,为了减少在实际输入代码时总是忘记初始化的问题,在结构体内部加上以下代码:

	bign(){memset(d,0,sizeof(d));len=0;}

因此大整数结构体就变成了这样:

struct bign{int d[1000];int len;bign(){memset(d,0,sizeof(d));len=0;}
};

这样在每次定义结构体变量时,都会自动对该变量进行初始化。

而输入大整数时,一般都是先用字符串读入,然后再把字符串另存为bign结构体。由于使用char数组进行读入时,整数的高位会变成数组的低位,而整数的低位会变成数组的高位,因此为了让整数在bign中是顺序存储,需要让字符串倒着赋给d[]数组。

bign change(char str[]){bign a;a.len=strlen(str);for(int i=0;i<a.len;i++){a.d[i]=str[a.len-i-1]-'0';}return 0;
}

如果要比较两个bign变量的大小,规则也很简单:先判断两者的 len大小,如果不相等,则以长的为大;如果相等,则从高位到低位进行比较,直到出现某一位不等,就可以判断两个数的大小。具体代码如下:

int compare(bign a,bign b){if(a.len>b.len){return 1;//a大 }else if(a.len<b.len){return -1;//b大 }else{for(int i=a.len-1;i>=0;i--){if(a.d[i]>b.d[i]){return 1;}else if(a.d[i]<b.d[i]){return -1;}}return 0;//两数相等 }
}

接下来主要介绍四个运算:(1)高精度加法;(2)高精度减法;(3)高精度与低精度的乘法;(4)高精度与低精度的除法。

大整数的四则运算

高精度加法

将改为上的两个数字和进位相加,得到的结果取个位数作为该位结果,取十位数作为新的进位。

bign add(bign a,bign b){bign c;int carry=0;//进位for(int i=0;i<a.len||i<b.len;i++){int temp=a.d[i]+b.d[i]+carry;c.d[c.len++]=temp%10;carry=temp/10;} if(carry!=0){c.d[c.len++]=carry;}return 0;
}

下面是完整的A+B的代码。

#include<stdio.h>
#include<string.h>
struct bign{int d[1000];int len;bign(){memset(d,0,sizeof(d));len=0;}
};
bign change(char str[]){bign a;a.len=strlen(str);for(int i=0;i<a.len;i++){a.d[i]=str[a.len-i-1]-'0';}return a;
}
bign add(bign a,bign b){bign c;int carry=0;for(int i=0;i<a.len||i<b.len;i++){int temp=a.d[i]+b.d[i]+carry;c.d[c.len++]=temp%10;carry=temp/10;}if(carry!=0){c.d[c.len++]=carry;}return c;
}
void print(bign a){for(int i=a.len-1;i>=0;i--){printf("%d",a.d[i]);}
}
int main(){char str1[1000],str2[1000];scanf("%s%s",str1,str2);bign a=change(str1);bign b=change(str2);print(add(a,b));return 0;
}

最后指出,这样写法的条件是两个对象都是非负整数。如果有一方是负的,可以在转换到数组这一步时去掉其负号,然后采用高精度减法;如果两者都是负的,就都去掉负号后用高精度加法,最后把负号再加回去即可。

高精度减法

对某一步,比较被减位和减位,如果不够减,则令被减位的高位减1, 被减位加10再进行减法;如果够减,则直接减。最后一步要注意减法后高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。

bign sub(bign a,bign b){bign  c;for(int i=0;i<a.len||i<b.len;i++){if(a.d[i]<b.d[i]){a.d[i+1]--;a.d[i]+=10;}c.d[c.len++]=a.d[i]-b.d[i];}while(c.len-1>=1&&c.d[c.len-1]==0){c.len--;}return c;
}

高精度减法的完整代码即为把上面的sub函数替代高精度加法中add函数的位置即可,记得 调用的时候也是用sub函数。

高精度与低精度的乘法

取bign的某位与int型整体相乘,再与进位相加,所得结果的个位数作为该位结果,高位部分作为新的进位。

bign multi(bign a,int b){bign c;int carry=0;for(int i=0;i<a.len;i++){int temp=a.d[i]*b+carry;c.d[c.len++]=temp%10;carry=temp/10;}while(carry!=0){c.d[c.len++]=carry%10;carry/=10;}return c;
}

完整的A*B的代码只需要把高精度加法中的add函数改成这里的multi函数,并注意输入的时候b是作为int型输入即可。

高精度与低精度的除法 

上一步的余数乘以10加上该步的位,得到该步临时的被除数,将其与除数比较:如果不够除,则该位的商为0;如果够除,则商即为对应的商,余数即为对应的余数。最后一位要注意减法后高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。

bign divide(bign a,int b,int& r){bign c;c.len=a.len;for(int i=a.len-1;i>=0;i--){r=r*10+a.d[i];if(r<b){c.d[i]=0;}else{c.d[i]=r/b;r=r%b;}}while(c.len-1>=1&&c.d[c.len-1]==0){c.len--;}return c;
}

在上述代码中,考虑到函数每次只能返回一个数据,而很多题目里面会经常要求得到余数,因此把余数写成引用的形式直接作为参数传入,或是把r设成全局变量。

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

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

相关文章

android requireActivity() 和 getActivity()使用问题

requireActivity() 和 getActivity() 都是从 Fragment 中获取宿主 Activity 的方法,但它们有一些不同的行为和使用场景。 requireActivity() 抛出异常:如果 Fragment 没有附加到任何 Activity,调用 requireActivity() 会抛出 IllegalStateException。安全性:通常在你确定 …

新品 | Forge® 1GigE IP67工业相机助力智能农业、食品和饮料行业

近日&#xff0c;51camera的合作伙伴Teledyne FLIR IIS推出Forge 1GigE IP67,它是Forge系列的最新工业相机&#xff0c;旨在在恶劣的工业环境中运行&#xff0c;同时确保高效的生产能力。Forge 1GigE IP67致力于为工厂自动化提供先进成像系统的最新产品。 Forge 1GigE IP67相机…

python-pytorch 实现seq2seq+luong general concat attention 完整代码

接上一篇https://blog.csdn.net/m0_60688978/article/details/139046644 # def getAQ(): # ask[] # answer[] # with open("./data/flink.txt","r",encoding"utf-8") as f: # linesf.readlines() # for line in lin…

MyBatis多数据源配置与使用,基于ThreadLocal+AOP

导读 MyBatis多数据源配置与使用其一其二1. 引依赖2. 配置文件3. 编写测试代码4. 自定义DynamicDataSource类5. DataSourceConfig配置类6. AOP与ThreadLocal结合7. 引入AOP依赖8. DataSourceContextHolder9. 自定义注解UseDB10. 创建切面类UseDBAspect11. 修改DynamicDataSourc…

jQuery里添加事件 (代码)

直接上代码 <!DOCTYPE html> <html><head></head><body><input type"text" placeholder"城市" id"city" /><input type"button" value"添加" id"btnAdd" /><ul id…

PTA 计算矩阵两个对角线之和

计算一个nn矩阵两个对角线之和。 输入格式: 第一行输入一个整数n(0<n≤10)&#xff0c;第二行至第n1行&#xff0c;每行输入n个整数&#xff0c;每行第一个数前没有空格&#xff0c;每行的每个数之间各有一个空格。 输出格式: 两条对角线元素和&#xff0c;输出格式见样例…

Android存储系统成长记

用心坚持输出易读、有趣、有深度、高质量、体系化的技术文章 本文概要 您一定使用过Context的getFileStreamPath方法或者Environment的getExternalStoragePublicDirectory方法&#xff0c;甚至还有别的方法把数据存储到文件中&#xff0c;这些都是存储系统提供的服务&#x…

PTA 判断两个矩阵相等

Peter得到两个n行m列矩阵&#xff0c;她想知道两个矩阵是否相等&#xff0c;请你用“Yes”&#xff0c;“No”回答她&#xff08;两个矩阵相等指的是两个矩阵对应元素都相等&#xff09;。 输入格式: 第一行输入整数n和m&#xff0c;表示两个矩阵的行与列&#xff0c;用空格隔…

修改元组元素

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 场景模拟&#xff1a;伊米咖啡馆&#xff0c;由于麝香猫咖啡需求量较大&#xff0c;库存不足&#xff0c;店长想把它换成拿铁咖啡。 实例08 将麝香猫…

chrome浏览器驱动下载

跑自动化的时候&#xff0c;需要打开谷歌浏览器&#xff0c;这个时候提示浏览器驱动找不到咋办呢&#xff1f; 1、网上搜索找到了这篇文章&#xff1a;https://www.cnblogs.com/laoluoits/p/17710501.html&#xff1b;按照文章介绍&#xff0c; 首先找到&#xff1a;CNPM Bin…

D - Permutation Subsequence(AtCoder Beginner Contest 352)

题目链接: D - Permutation Subsequence (atcoder.jp) 题目大意&#xff1a; 分析&#xff1a; 相对于是记录一下每个数的位置 然后再长度为k的区间进行移动 然后看最大的pos和最小的pos的最小值是多少 有点类似于滑动窗口 用到了java里面的 TreeSet和Map TreeSet存的是数…

解决 Spring Boot 应用启动失败的问题:Unexpected end of file from server

解决 Spring Boot 应用启动失败的问题&#xff1a;Unexpected end of file from server 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的…

Spring AOP失效的场景事务失效的场景

场景一&#xff1a;使用this调用被增强的方法 下面是一个类里面的一个增强方法 Service public class MyService implements CommandLineRunner {private MyService myService;public void performTask(int x) {System.out.println("Executing performTask method&quo…

爬虫学习--15.进程与线程(2)

线程锁 当多个线程几乎同时修改某一个共享数据的时候&#xff0c;需要进行同步控制 某个线程要更改共享数据时&#xff0c;先将其锁定&#xff0c;此时资源的状态为"锁定",其他线程不能改变&#xff0c;只到该线程释放资源&#xff0c;将资源的状态变成"非锁定…

Linux如何设置共享文件夹

打开虚拟机->菜单->虚拟机设置->选项->共享文件夹->总是启用。点击添加按钮->弹出添加向导->点击浏览按钮&#xff0c;从windows中选择一个文件夹&#xff0c;确定即可。

[Windows] GIF动画、动图制作神器 ScreenToGif(免费)

ScreenToGif 是开源免费的 Gif 动画录制工具&#xff0c;小巧原生单文件&#xff0c;功能很实用。它有录制屏幕、录制摄像头、录制画板、图像编辑器等功能&#xff0c;可以将屏幕任何区域及操作过程录制成 GIF 格式的动态图像。保存前还可对 GIF 图像编辑优化&#xff0c;支持自…

末日设计1.00

故事背景: 在不远的未来&#xff0c;世界陷入了末日危机。资源枯竭、社会秩序崩溃&#xff0c;幸存者们为了生存&#xff0c;不得不拿起武器争夺每一寸土地和每一口食物。在这个混乱的世界中&#xff0c;你是一名传奇狙击手&#xff0c;凭借超凡的射击技巧和生存智慧&#xff0…

研二学妹面试字节,竟倒在了ThreadLocal上,这是不要应届生还是不要女生啊?

一、写在开头 今天和一个之前研二的学妹聊天&#xff0c;聊及她上周面试字节的情况&#xff0c;着实感受到了Java后端现在找工作的压力啊&#xff0c;记得在18&#xff0c;19年的时候&#xff0c;研究生计算机专业的学生&#xff0c;背背八股文找个Java开发工作毫无问题&#x…

本地图形客户端查看git提交历史 使用 TortoiseGit

要在本地查看提交记录和修改历史&#xff0c;可以使用 TortoiseGit 和 Git-SCM。这两个工具都提供了强大的功能来管理和查看 Git 仓库中的提交记录和历史修改。 使用 TortoiseGit 查看提交记录和修改历史 查看提交记录&#xff08;Log&#xff09;&#xff1a; 右键点击项目文…

抖音里卖什么最赚钱?4个冷门的高利润商品,还有谁不知道!

哈喽~我的电商月月 做抖音小店的新手朋友&#xff0c;一定很想知道&#xff0c;在抖音里卖什么最赚钱&#xff1f; 很多人都会推荐&#xff0c;日常百货&#xff0c;小风扇&#xff0c;女装&#xff0c;宠物用品等等&#xff0c;这些商品确实很好做&#xff0c;你们可以试试 …