高精度加减乘除

news2025/8/2 18:42:13

高精度加法

对于给定的两个特别大的数我们用两个字符串来接收 s1s2

例如:对于两个数 5621545595425453,即 s1 = "56215455" , s2 = "95425453"

对于这两个数,分别用两个列表 ab来接收(例如:C++ 用 vector,Java 用 List)它们。

对于上面的例子: a = {5,6,2,1,5,4,5,5} , b = {9,5,4,2,5,4,5,3}

接着对这两个数模拟 竖式计算

ab的最后一位数开始向前模拟计算。
在这里插入图片描述
代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

//用来接收两个数的
string s1,s2;

vector<int> add(vector<int>& a,vector<int>& b){

    int m = a.size(),n = b.size();
    
    vector<int> c;
    //分别从 a 和 b 的最后一位开始模拟
    //ca 是进位,初始进位为0
    int i = m - 1,j = n - 1,ca = 0;
    
    //a 没计算完 ,b 没计算完,ca 进位是1 就继续模拟
    while(i >= 0 || j >= 0 || ca){
        //sum 是需要加上每次的进位的,这里直接初始化为 ca
        int sum = ca;
        //如果 a 没计算完,就继续计算,否则忽略
        if(i >= 0){
            sum += s1[i] - '0';
            i--;
        }
        //如果 b 没计算完,就继续计算,否则忽略
        if(j >= 0){
            sum += s2[j] - '0';
            j--;
        }
        //sum / 10 的余数就是我们已经计算得出的结果 记录下来
        c.push_back(sum % 10);
        //更新进位
        ca = sum / 10;
    }
    //因为我们是从 a 和 b 的低位开始模拟的,答案也是先记录的低位和 所以需要反转过来
    //例如 a = {1,2,3} b = {4,5,6}
    // c = {9,7,5} 正确答案应该是 579 需要反转一下
    reverse(c.begin(),c.end());
    
    return c;
}

int main(){
    //接收两个数
    getline(cin,s1);
    getline(cin,s2);
    
    //a 和 b 分别是装两个数的容器
    vector<int> a,b;
    int m = s1.size(),n = s2.size();
    
    for(int i = 0;i < m;i++) a.push_back(s1[i] - '0');
    for(int i = 0;i < n;i++) b.push_back(s2[i] - '0');
    
    //c就是装有结果的容器
    auto c = add(a,b);
    
    for(auto x:c) printf("%d",x);
    return 0;
}

高精度减法

我们继续分别用两个列表 ab来接收 被减数 和 减数。

在这里插入图片描述
模拟减法的过程,先是 B 0 − A 0 B_0 - A_0 B0A0,有两种情况:

  • 如果 B 0 − A 0 > = 0 B_0 - A_0 >= 0 B0A0>=0,就不用管,直接减
  • 如果 B 0 − A 0 < 0 B_0 - A_0 < 0 B0A0<0,那么 B 0 B_0 B0就不够减,需要向 B 1 B_1 B1借位,此时就是 10 + B 0 − A 0 10 + B_0 - A_0 10+B0A0,借位之后 B 1 B_1 B1 也要减去借位 1

我们用 t表示借位。

此外,高精度减法 与 高精度加法相比,还有两个需要注意的点:

  • 我们要保证是 大数小数,因为我们要保证是 数位多的数位少的

    • 如果 a − b > = 0 a - b >= 0 ab>=0,那么 a-b
    • 如果 a − b < 0 a - b < 0 ab<0,那么 b-a,最后在答案前面加一个 -号。
  • 要去掉多余的前导0。(例如:a = 1234 , b = 1230,那么 a - b = 4,实际上我们存储答案的时候 是倒着存的,把0也存了进去,实际上存的是 4000,所以需要把这些 0去掉)。

代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

string s1,s2;

//判断 a 是否大于等于 b
bool cmp(vector<int>& a,vector<int>& b){
    if(a.size() != b.size()) return a.size() > b.size();
    
    for(int i = 0;i < a.size();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 m = a.size() , n = b.size();
    
    for(int i = m - 1,j = n - 1,t = 0;i >= 0;i--){
        int sum = a[i] - t;
        if(j >= 0){
            sum -= b[j];
            j--;
        }
        //包含两种情况
        //1. sum = a[i] - b[i] - t < 0 , 这时就需要借位 (10 + sum) % 10 就等于 sum + 10
        //2. sum = a[i] - b[i] - t >= 0, 这时直接减 , (sum + 10) % 10 还是等于 sum
        c.push_back((sum + 10) % 10);
        
        //判断是否要借位,sum < 0,说明不够减 才需要借位
        if(sum < 0) t = 1;
        else t = 0;
    }
    
    //去除多余的前导0
    while(c.size() > 1 && c.back() == 0) c.pop_back();
    
    //将答案翻转过来
    reverse(c.begin(),c.end());
    
    return c;
}

int main(){
    getline(cin,s1);
    getline(cin,s2);
    
    vector<int> a,b;
    
    int m = s1.size() , n = s2.size();
    for(int i = 0;i < m;i++) a.push_back(s1[i] - '0');
    for(int i = 0;i < n;i++) b.push_back(s2[i] - '0');
    
    //如果 a >= b , 直接 a - b
    if(cmp(a,b)){
        auto c = sub(a,b);
        for(auto x:c) printf("%d",x);
    }
    //如果 a < b , 直接 b - a , 在答案前面添加 一个 - 号
    else{
        auto c = sub(b,a);
        printf("-");
        for(auto x:c) printf("%d",x);
    }
    return 0;
}

高精度乘法

我们继续分别用两个列表 ab来接收两个数。

我们已知 两个数的乘积的长度 一定不大于 两个数分别的长度。例如,两个数 abcdef的乘积的长度一定不大于 6

我们令 m = a.size() , n = b.size(),对于存放两个数乘积的 csize应该是 m+n

我们定义 c[k]是所有 a[i] * b[j]i + j == k)的和。

接着我们再处理 c,把里面的每一个数都放在合适的位置。

同时也要注意处理前导零。(因为存在 a == 0或者 b==0的情况)。

代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

string s1, s2;

vector<int> mul(vector<int>& a, vector<int>& b) {
    int m = a.size() , n = b.size();
    vector<int> c(m + n);
    
    //c[i+j] 等于 所有 a[i] * b[j]的和
    //为了方便处理 这里就没有逆序处理
    //如果 s1 = 123 s2 = 456
    //那么 a = 321 b = 654
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            c[i + j] += a[i] * b[j];
        }
    }

    //处理 c 
    for (int i = 0, ca = 0; i < c.size() || ca; i++) {
        ca += c[i];
        if (i < c.size()) c[i] = ca % 10;
        else c.push_back(ca % 10);

        ca /= 10;
    }
    //去除前导0
    while (c.size() > 1 && c.back() == 0) c.pop_back();

    reverse(c.begin(), c.end());
    return c;
}

int main() {

    getline(cin, s1);
    getline(cin, s2);

    vector<int> a, b;
    int m = s1.size() , n = s2.size();
    //为了方便处理 这里从低位到高位存储
    for (int i = m - 1; i >= 0; i--) a.push_back(s1[i] - '0');
    for (int i = n - 1; i >= 0; i--) b.push_back(s2[i] - '0');

    auto c = mul(a, b);

    for (auto x : c) {
        printf("%d", x);
    }

    return 0;
}

高精度除法

这里的高精度除法 是一个 非常大的数 a➗一个较小的数 b

跟其他几个不同的是,除法 是从高位向低位开始➗的

例如,123 ➗ 45,是从a的最高位 1开始➗的。

在模拟除法的时候,需要用余数 r来参与到下一位数的除法。

高精度除法也需要去除前导0。例如,100 ➗ 9商是 011,余数是 1,商需要去掉前面的 0,所以应该是 11

代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

vector<int> division(vector<int>& a,int b,int& r){
    vector<int> c;
    int m = a.size();
    
    //从高位开始除
    for(int i = 0;i < m;i++){
        r = r * 10 + a[i];
        c.push_back(r / b);
        r = r % b;
    }
    //123 ➗ 13 商是 09 余数r = 6
    //所以我们需要先把 c 翻转过来,方便我们去除前导0 ,翻转过来后为 90
    reverse(c.begin(),c.end());
    
    //取除前导0
    while(c.size() > 1 && c.back() == 0) c.pop_back();
    
    //去除完毕之后,再将商翻转回来
    reverse(c.begin(),c.end());
    
    return c;
}

int main(){
    string s1;
    int b;
    
    getline(cin,s1);
    
    cin>>b;
    
    vector<int> a;
    int m = s1.size();
    
    for(int i = 0;i < m;i++) a.push_back(s1[i] - '0');
    
    //r 是余数
    int r = 0;
    
    auto c = division(a,b,r);
    
    for(auto x:c) printf("%d",x);
    
    //先换行 再输出余数 r
    cout<<endl<<r<<endl;
}

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

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

相关文章

LeetCode-78. 子集

题目来源 78. 子集 题目思路 其实子集也是一种组合问题&#xff0c;因为它的集合是无序的&#xff0c;子集{1,2} 和 子集{2,1}是一样的。 那么既然是无序&#xff0c;取过的元素不会重复取&#xff0c;写回溯算法的时候&#xff0c;for就要从startIndex开始&#xff0c;而在这…

华为OD机试题,用 Java 解【比赛评分】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

开源单点登录MaxKey和JeeSite 单点登录集成指南

1. JeeSite介绍 JeeSite 隶属于济南卓源软件有限公司&#xff0c;是一个 Java 快速开发平台&#xff0c; 基于经典技术组合&#xff08;Spring Boot、Shiro、MyBatis、BeetlBootstrap or TSVue3&#xff09;在线代码生成工具&#xff0c; 支持 Spring Cloud 架构&#xff0c;分…

MYSQL 索引失效的十个场景(一)

一、查询条件包含or&#xff0c;可能导致索引失效 新建一个student表&#xff0c;它有一个普通索引userId&#xff0c;结构如下&#xff1a; CREATE TABLE student (id varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,name varchar(50) COLLATE utf8mb4_unicode_ci DEFAUL…

移动端适配的理解和各种方案解析(详解)

前言&#xff1a;最近在弄移动端项目&#xff0c;记录一下移动端的应用方案。对各个方案的解决理解。 目录 1.什么是移动端适配 2.理解视口viewport 2.1PC端的视口 2.2移动端的视口 2.2.0 PC端的网页在移动端显示的问题 2.2.1 布局视口 2.2.2 视觉视口 (visual viewport) …

一看就懂的Semaphore源码解析,诸佬们快来看看吧

前言&#xff1a;一位朋友问到了我Semaphore类相关的知识&#xff0c;简单看了一下源码复习了一下&#xff0c;写下本篇文章做一个回顾。 希望能够加深自己的印象以及帮助到其他的小伙伴儿们&#x1f609;&#x1f609;。 如果文章有什么需要改进的地方还请大佬不吝赐教&#x…

华为OD机试题,用 Java 解【航天器】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

CSCode 配置一条龙 CPP/CC

下载 官⽹下载地址&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 下载太慢&#xff0c;推荐⽂章&#xff1a;解决VsCode下载慢问题_wang13679201813的博客-CSDN博客_vscode下载慢 安装 无脑下一步 推荐插件 免配置&#xff1a; 1. Remote - SSH - 远程…

Exception has occurred: ModuleNotFoundErrorNo module named ‘urllib3‘【已解决】

问题描述 实际上只是想要测试一下torch是否安装成功&#xff0c;输出相应版本。谁知道就报错了。 Exception has occurred: ModuleNotFoundError No module named urllib3 解决方案 &#xff08;1&#xff09;使用pip或者conda卸载urllib3 pip uninstall urllib3conda unin…

离散无记忆与有记忆信源的序列熵

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;information-theory】&#xff0c;需要的朋友们自取。或者公众号【AIShareLab】回复 信息论 也可获取。 文章目录离散无记忆信源的…

以高能低碳技术融入PC全生命周期,英特尔联合业界推出绿色商用电脑

双碳既是关系到地球上每个人的大话题&#xff0c;也是IT系统和产品降本增效的重要手段。 英特尔将高能低碳新理念融入从PC定义设计到回收循环的全生命周期 4 大关键环节&#xff0c;值得参考。 碳达峰、碳中和这个“双碳”的话题貌似与技术开发者个人距离很远。其实&#xff0c…

骨传导耳机是怎么传声的,选择骨传导耳机的时候需要注意什么?

​骨传导耳机之所以能够成为当下最火的耳机&#xff0c;骨传导技术将声音转化为震动感&#xff0c;通过骨头进行传播&#xff0c;不会堵塞耳朵&#xff0c;就不会影响到周围环境音。这种技术也让骨传导耳机比传统入耳式耳机更安全&#xff0c;无需入耳式设计&#xff0c;避免了…

小猫小狗玩数学-第14届蓝桥杯STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第102讲。 蓝桥杯选拔赛现已更名为STEMA&#xff0c;即STEM 能力测试&#xff0c;是蓝桥杯大赛组委会与美国普林斯顿多…

蓝牙运动耳机哪个好,比较好的运动蓝牙耳机

很多想选择蓝牙运动耳机的朋友都不知道应该如何选择&#xff0c;运动首先需要注意的就是耳机的防水能力以及耳机佩戴舒适度&#xff0c;在运动当中会排出大量的汗水&#xff0c;耳机防水等级做到越高&#xff0c;可以更好地保护耳机不受汗水浸湿&#xff0c;下面就分享五款适合…

智能电视“套娃式”收费背后的自我救赎

配图来自Canva可画 近年来随着智能化浪潮的迅速铺开&#xff0c;与以前只能看电视的智能电视相比&#xff0c;现在的智能电视还能打游戏、听音乐&#xff0c;用户还可在电视上自行下载、安装、卸载应用软件&#xff0c;功能大大丰富了。但随着智能电视功能的逐渐增多&#xff…

我们应该如何优雅的处理 React 中受控与非受控

引言 大家好&#xff0c;我是19组清风。有段时间没有和大家见面了&#xff0c;最近因为有一些比较重要的事情&#xff08;陪女朋友和换了新公司&#xff09;在忙碌所以销声匿迹了一小段时间&#xff0c; 后续会陆陆续续补充之前构建 & 编译系列中缺失的部分&#xff0c;提…

day 33 状态压缩dp

二维状态压缩dp对于解决哈密顿回路问题的状态压缩dp只能计算固定起点到其他点的总方案数或最小路径等回路计数小蓝现在在第一栋教学楼&#xff0c;他想要访问每栋教学楼正好一次&#xff0c;最终回到第一栋教学楼&#xff08;即走一条哈密尔顿回路&#xff09;可看做&#xff1…

华为OD机试题,用 Java 解【计算面积】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

索引的创建与设计原则

1.索引的声明与使用 1.1索引的分类 MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。 从 功能逻辑 上说&#xff0c;索引主要有 4 种&#xff0c;分别是普通索引、唯一索引、主键索引、全文索引。按照 物理实现方式&#xff0c;索引可以分…

【编程基础之Python】6、Python基础知识

【编程基础之Python】6、Python基础知识Python基础知识Python的基本要素模块语句表达式注释Python的代码格式Python基础知识 Python 是一种高级的、动态的、解释型的编程语言&#xff0c;具有简单易学、开发效率高、可读性强等特点&#xff0c;广泛应用于数据科学、Web 开发、…