C++手搓大整数类

char是8位的,short是16位的,int是32位的,最大的long long是64位的,也就是说基本的数据类型无法表示超过2的64次方-1的数

如今又到了找工作的时候了,面试手撕题少不了,听说这个手搓大整数也有过面试题,这里先搓一手,免得以后执手相看泪眼

其实Java有这个大整数类,手搓大整数类可以说是一个比较综合的应用,需要使用到重载运算符,包括输入输出、四则运算等等,还需要字符串的运算,其中比较运算符的实现是十分巧妙的,这里的思维应用、逻辑运算都是很好的训练,这里只实现了大整数相加的功能,源码已开源在MaolinYe/BigInteger: 使用C++11实现的一个大整数类 (github.com)

欢迎大家指正修改 

目录

基本思路 

重载赋值运算符 

重载输入输出运算符 

重载加运算符

重载比较运算符


基本思路 

实现大整数有两种方法,一种是将大数当成字符来处理,手动计算加减乘除,另一种则是将大数分成多个小部分用基本类型存储处理

我们这里实现第二种方法的,目前版本是支持非负整数

基本思路是将一个大整数切分成几段小的用int存储,用vector容器来存储每段,例如

1111222233334444 integer[1]=11112222 integer[0]=33334444

重载赋值运算符 

重载赋值运算符,实现从基本数据类型到大整数的转换,通过和base取余切分出段

class BigInteger {static const int width = 8; // 切分段的长度static const int base = 1e8; // 切分段的数量级vector<int> integer; // 存储各个段int segments = 0; // 切分的段数BigInteger operator=(long long num) { // 重载赋值运算符,从基本数据类型转换大整数存储integer.clear();do {integer.emplace_back(num % base);num /= base;segments++;} while (num > 0);return *this;}
};

实现默认构造函数和带参构造函数,通过重载的赋值运算符直接赋值

    explicit BigInteger(long long num = 0) {*this = num;}

继续重载赋值运算符,实现从字符串到大整数的转换,首先计算出这个大整数有几段,这里的计算方法十分巧妙,如果直接除以width当不是整除的时候会少数一段,所以先减一再除最后加一的方法可以适用整除和不整除的情况

然后需要计算每段的开始和结束的位置,因为vector存储段的顺序是从后往前,所以这里计算段的位置也是从后往前,然后通过string取子串,再通过stoi函数将字符串转成整型存储

    BigInteger operator=(const string &num) { // 重载赋值运算符,从字符串类型转大整数存储integer.clear();int length = num.size();segments = (length - 1) / width + 1; // 这里计算段数的方法十分巧妙for (int i = 0; i < segments; i++) {int end = length - i * width; // 计算每段结束的地方,从最后一段开始int start = max(0, end - width); // 计算每段开始的地方integer.emplace_back(stoi(num.substr(start, end - start))); // 字符串转整数}return *this;}

重载输入输出运算符 

接着重载输出运算符,重载输出运算符可以通过友元函数和成员函数两种方法实现,我们这里通过友元函数的方法实现,倒序输出vector

    ostream &operator<<(ostream &out) { // 重载输出运算符,vector倒着输出for (auto it = integer.rbegin(); it != integer.rend(); it++) {cout << *it;}return out;}

重载输入运算符,将输入当成字符串,通过重载的赋值运算符直接赋值

    istream &operator>>(istream &in) { // 重载输入运算符,当成字符串输入,用重载的赋值运算符直接赋值string num;in >> num;*this = num;return in;}

重载加运算符

大整数加运算的基本思想是将各个段相加,需要处理段相加的时候出现的进位情况,由于int型可以表示的范围大概是10个数量级,而我们给每段设置的位数是8,因此可以使用int型来存储段加的结果,然后继续存储加结果和base取余的结果,计算出和base整除的结果,留到下一个段继续相加

    BigInteger operator+(const BigInteger &bigInteger) const {BigInteger result;for (int i = 0, carry = 0; carry || i < segments || i < bigInteger.segments; i++) {if (i < segments)carry += integer[i];if (i < bigInteger.segments)carry += bigInteger.integer[i];result.integer.emplace_back(carry % base);result.segments++;carry = carry / base;}return result;}

顺便实现+=

    BigInteger operator+=(const BigInteger &bigInteger) {*this = *this + bigInteger;return *this;}

重载比较运算符

这个比较两个大整数的实现比较巧妙

我们先实现一个重载小于的判断,先比较两个大整数的段数,如果段数不同直接返回段数的比较就行,如果段数相同,由于大整数的低位存储在vector的前面,所以从后面段开始比较高位,如果高位不相同,那么返回高位的比较结果就行,如果都相同,那么说明相等

    bool operator <(const BigInteger&bigInteger) const{if(segments!=bigInteger.segments)return segments<bigInteger.segments;for(int i=segments-1;i>=0;i--){ // 倒着比较,因为低位在vector的前面,先比较高位if(integer[i]!=bigInteger.integer[i])return integer[i]<bigInteger.integer[i];}return false; // 相等}

然后接下来的大于、大于等于、小于等于、不等于、等于都可以通过小于实现

    bool operator>(const BigInteger &bigInteger) const {return bigInteger < *this; // a大于b等价于b小于a}bool operator<=(const BigInteger &bigInteger) const {return !(bigInteger < *this); // a<=b等价于b不小于a}bool operator>=(const BigInteger &bigInteger) const {return !(*this < bigInteger); // a>=b等价于a不小于b}bool operator!=(const BigInteger &bigInteger) const {return *this < bigInteger || bigInteger < *this; // a不等于b等价于a大于b或者小于b}bool operator==(const BigInteger &bigInteger) const {return !(*this < bigInteger) && !(bigInteger < *this); // a等于b等价于a既不大于b也不小于b}

巧妙

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

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

相关文章

MySQL索引的管理索引的使用原则以及SQL优化

索引的管理 查看索引 SHOW INDEX(或KEYS) FROM 表名; 删除索引 ALTER TABLE 表名 DROP PRIMARY KEY; DROP INDEX 索引名 ON 表名; ALTER TABLE 表名 DROP INDEX 索引名; 修改索引 ALERT TABLE 表名 ADD 索引类型&#xff08;数据列名&#xff09;;…

Java算法 图 连通性 刷题记录

Java算法 图 & 连通性 刷题记录 连通性&#xff0c;以及图&#xff1b; UnionSet或者 Map<String,HashMap>; 连通性&#xff0c;假设a<b, 则值包含a的&#xff0c;也都把b加进去 递归 数独 用3个boolean的check&#xff0c; rowCheck、colCheck、squareCheck 递…

CSS 实现卡片以及鼠标移入特效

CSS 实现卡片以及鼠标移入特效 文章目录 CSS 实现卡片以及鼠标移入特效0、效果预览默认鼠标移入后 1、创建卡片组件2、添加样式3、完整代码 0、效果预览 默认 鼠标移入后 在本篇博客中&#xff0c;我们将探讨如何使用 CSS 来实现卡片组件&#xff0c;并添加鼠标移入特效&#…

基于嵌入式的智能智能通风系统

基于嵌入式的智能智能通风系统 功能说明 通过微信小程序控制窗户的开关状体以及倒计时开关和定时开关&#xff0c;小程序上实时显示当前温度湿度和光照强度。 功能展示 02智能通风系统 Mqtt服务器 http://www.yoyolife.fun/iot&#xff1a;Mqtt服务器&#xff0c;我是在这里注…

Web自动化测试中的接口测试

1、背景 1.1 Web程序中的接口 1.1.1 典型的Web设计架构 web是实现了基于网络通信的浏览器客户端与远程服务器进行交互的应用&#xff0c;通常包括两部分&#xff1a;web服务器和web客户端。web客户端的应用有html&#xff0c;JavaScript&#xff0c;ajax&#xff0c;flash等&am…

Js中改变this的方法

在JavaScript中&#xff0c;你可以使用几种不同的方法来改变函数的this值。以下是其中的一些方法&#xff1a; 使用Function.prototype.bind()方法 bind()方法创建一个新的函数&#xff0c;当这个新函数被调用时&#xff0c;bind()的第一个参数将成为thisArg&#xff0c;后续…

Linux下进程子进程的退出情况

进程的退出分为了两大类&#xff0c;一类是正常的退出&#xff0c;另一类是非正常的退出。 正常退出时有五种情况&#xff0c;分别是 ①main函数调用return ②进程调用exit(),标准c库 ③进程调用_exit()或者_Exit()&#xff0c;属于系统调用 ④进程最后一个线程返回 ⑤最…

linux单机部署mysql(离线环境解压即可)

一、下载官网压缩包&#xff08;tar.gz&#xff09; MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/根据自己的操作系统发行版本、位数、gclib版本、mysql版本来选择对应的压缩包 比如我是 linux系统debian10&#xff08;官网只有linux ge…

vue:菜单栏联动内容页面tab

一、需求 需要实现效果&#xff1a;左侧菜单栏与右侧内容部分联动&#xff0c;当点击左侧的菜单&#xff0c;右侧会展示对应的tab&#xff0c;没有点击时&#xff0c;不展示&#xff08;如刚进入页面没有点击菜单&#xff0c;则没有tab&#xff09;&#xff1b;点击后没有关闭…

玖章算术NineData通过阿里云PolarDB产品生态集成认证

近日&#xff0c;玖章算术旗下NineData 云原生智能数据管理平台 (V1.0&#xff09;正式通过了阿里云PolarDB PostgreSQL版 (V11)产品集成认证测试&#xff0c;并获得阿里云颁发的产品生态集成认证。 测试结果表明&#xff0c;玖章算术旗下NineData数据管理平台 (V1.0&#xff…

美易平台:JMP证券将Meta Platforms的目标价格上调至410美元。

JMP证券最近发布了一份研究报告&#xff0c;将Meta Platforms&#xff08;前身为Facebook&#xff09;的目标价格上调至410美元&#xff0c;并将Alphabet&#xff08;谷歌母公司&#xff09;的目标价格上调至150美元。这一消息引起了市场的广泛关注。 根据JMP证券的分析师们的…

Maxwell介绍

一、介绍 介绍&#xff1a;它读取MySQL binlog并将数据更改作为JSON写入Kafka、Kinesis和其他流媒体平台&#xff08;目前支持&#xff1a;kafka、RabbitMQ、Redis、file、Kinesis、Nats、Google Cloud Pub/Sub、Google Cloud Bigquery、SNS&#xff09; 版本&#xff1a;从v1.…

【车载开发系列】Autosar DCM诊断管理模块

【车载开发系列】Autosar DCM诊断管理模块 【车载开发系列】Autosar DCM诊断管理模块 【车载开发系列】Autosar DCM诊断管理模块一. DCM模块概念二. DCM模块与Autosar其他模块关系1&#xff09;Dcm和PduR的交互2&#xff09;Dcm和ComM模块的交互3&#xff09;Dcm和Dem的交互4&a…

RocketMQ常见面试题及答案梳理

1、RocketMQ有什么作用&#xff1f; 异步:数据的产生方不需要关心谁来使用数据&#xff0c;只需要将数据发送到broker,后续需要管消费流程&#xff0c;Rocket也有保证消息可靠性的方案消峰&#xff1a;正常业务系统当流量激增时&#xff0c;有可能会将系统压垮&#xff0c;有了…

H12-821_324

324.以下关于AC漫游组的描述,说法错误的是? A.漫游组的AC需要部署一台Master Controller B.AC可担任多个漫游组的漫游组服务器&#xff0c;同时自身可加入多个漫游组 C.Master Contoller必须为漫游组内的AC D.STA只能在同一个漫游组内的AC间才能进行漫游 答案&#xff1a;BC …

ChatGPT正确打开方式与GPT-4.5的key最新获取方式

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言4.5key价格泄漏ChatGPT4.0使用地址ChatGPT正确打开方式最新功能语音助手存档…

【2015~2024】大牛直播SDK演化史

大牛直播SDK的由来 大牛直播SDK始于2015年&#xff0c;最初我们只是想做个低延迟的RTMP推拉流解决方案&#xff0c;用于移动单兵等毫秒级延迟的场景下&#xff0c;我们先是实现了Android平台RTMP直播推送模块&#xff0c;当我们用市面上可以找到的RTMP播放器测试时延的时候&am…

网络设备的分类和功能、机柜布局、网络设备安装

网络互连设备根据不同层实现的机理不一样&#xff0c;又具体分为五类&#xff1a; 1、网络传输介质互联设备 2、网络物理层互联设备 3、数据链路层互联设备 4、网络层互联设备 5、应用层互联设备 常用设备 网络互联设备--互联设备 1、中继器 中继器是局域网互连的最简单…

恒创科技:云存储和网盘怎么区分出来?

随着互联网的发展&#xff0c;数据存储已成为人们日常生活中不可或缺的一部分。云存储和网盘是经常被人们提及的两种存储方式&#xff0c;均通过网络进行数据存储和访问的服务。但&#xff0c;它们在技术实现、数据安全性、访问方式和数据容量等方面存在一定的差异。要区分&…

三甲医院预约挂号系统源码,具备后台管理端和用户使用端,用户使用端包括:微信公众号、支付宝小程序

随着医疗行业的不断发展&#xff0c;预约挂号管理系统已成为医院管理中不可或缺的一部分。 预约挂号管理系统是一款综合性的预约挂号管理系统&#xff0c;帮助医院实现全方位的信息化管理&#xff0c;提高医疗服务质量和效率。支撑公众号、小程序、手机网上预约。 一款服务适用…