(基础算法)高精度加法,高精度减法

news2024/11/25 9:49:49

高精度加法

  1. 什么叫做高精度加法呢?包括接下来的高精度减法,高精度乘法与除法都是同一个道理。正常来讲的话加减乘除,四则运算的数字都是整数,也就是需要在int的范围之内,但当这个操作数变得非常"大"的时候(其实就是一个字符串,比方说有一个数是20位,如果用整数视角来看待的话,天方夜谭,没有数据类型能放得下它,所以它此刻是一个字符串了)。高精度运算操作的对象就是这些字符串化的巨大数字
  2. 对于高精度加法而言,这些操作数实际上是一些字符串,首先是将数字读进来,并且计算一下字符串的长度,字符串的长度实际上就是数字的位数
//输入
scanf("%s %s",num1,num2);
//计算字符串数组的长度
int sz1=strlen(num1);
int sz2=strlen(num2);
//
int s1=sz1-1;
int s2=sz2-1;
  1. 然后就进行加法的操作,这边需要一个变量t,用来记录一下是否需要进位。
int t=0;
  1. 然后输入的字符串当中最后一位才是数字的个位数,加法操作需要从个位开始加,所以说对于两个字符串而言,需要从后往前依次遍历。并且需要注意字符与数字之间的转化。
int t=0;
while(s1>=0 && s2>=0)
{
    int num=(num1[s1--]-'0')+(num2[s2--]-'0')+t;
    if (num>9)
    {
        t=1;
        num%=10;
    }
    else
    {
        t=0;
    }
    ans[k++]=num+'0';
}
  1. 两个字符串同时从后往前依次遍历,一开始肯定是齐头并向,但到最后肯定会有其中一个字符串先走完。此时就退出上面的while循环,接下来进行判断处理,也就是说哪个字符串还没有走完,就单独去处理这个字符串。在处理的过程当中必须得保留之前的进位,万一之前有进位的话,这边需要继续加上去。
while(s1>=0)
{
    int num=(num1[s1--]-'0')+t;
    if (num>9)
    {
        t=1;
        num%=10;
    }
    else
    {
        t=0;
    }
    ans[k++]=num+'0';
}
while(s2>=0)
{
    int num=(num2[s2--]-'0')+t;
    if (num>9)
    {
        t=1;
        num%=10;
    }
    else
    {
        t=0;
    }
    ans[k++]=num+'0';
}
  1. 当单独处理完之后并没有结束,此刻还需要去特判一下这个进位表示变量t是否等于1,如果说此刻他还等于1,这就说明还要继续去进一位。
if (t==1)
{
     ans[k++]='1';
 }
  1. 至此,我们已经把这两个数相加的形成的和的所有位数都已经放到新数组当中。但由于我们是从数组的从前往后放,也就意味着开始是数字的个位数。为了字符串打印出来符合视觉直觉,所以说我们还需要把这个结果数组给他倒置一下。
void reverse(char* arr, int l, int r)
{
    while(l<r)
    {
        char tmp=arr[l];
        arr[l]=arr[r];
        arr[r]=tmp;
        l++;
        r--;
    }
}

reverse(ans,0,k-1);

经典例题

luck
在这里插入图片描述

#include <stdio.h>
#include <string.h>
#define N 100010
char num1[N];
char num2[N];
char ans[N];
int k=0;
//数组反转
void reverse(char* arr, int l, int r)
{
    while(l<r)
    {
        char tmp=arr[l];
        arr[l]=arr[r];
        arr[r]=tmp;
        l++;
        r--;
    }
}
int main()
{
    //输入
    scanf("%s %s",num1,num2);
    //计算字符串数组的长度
    int sz1=strlen(num1);
    int sz2=strlen(num2);
    //
    int s1=sz1-1;
    int s2=sz2-1;
    //
    int t=0;
    while(s1>=0 && s2>=0)
    {
        int num=(num1[s1--]-'0')+(num2[s2--]-'0')+t;
        if (num>9)
        {
            t=1;
            num%=10;
        }
        else
        {
            t=0;
        }
        ans[k++]=num+'0';
    }
    while(s1>=0)
    {
        int num=(num1[s1--]-'0')+t;
        if (num>9)
        {
            t=1;
            num%=10;
        }
        else
        {
            t=0;
        }
        ans[k++]=num+'0';
    }
    while(s2>=0)
    {
        int num=(num2[s2--]-'0')+t;
        if (num>9)
        {
            t=1;
            num%=10;
        }
        else
        {
            t=0;
        }
        ans[k++]=num+'0';
    }
    if (t==1)
    {
        ans[k++]='1';
    }
    reverse(ans,0,k-1);
    printf("%s\n",ans);
    return 0;
}

高精度减法

  1. 高精度减法的话比高精度加法要更加复杂一些,先由于是高精度嘛,所以我们先把字符串给他读进来,并且计算一下两个字符串的大小。
scanf("%s %s",num1,num2);
int sz1=strlen(num1);
int sz2=strlen(num2);
  1. 然后我们这边需要实现一个两个字符串相减的函数,我们这边的模板是必须是第一个数比第二个数要大,那首先我们得判断一下这两个字符串所代表的整数到底哪个大?先实现一个函数判断大小
int cmp(int sz1, int sz2)
{
    if(sz1>sz2)
    {
        return 1;
    }
    else if (sz1<sz2)
    {
        return 2;
    }
    else
    {
        for (int i=0;i<sz1;i++)
        {
            if (num1[i]>num2[i])
            {
                return 1;
            }
            else if (num1[i]<num2[i])
            {
                return 2;
            }
        }
        return 0;
    }
}
  1. 然后当我们判断出来两个数的大小关系之后,然后根据大小关系给他把参数传到实现两个字符串所代表的整数相减的这个函数里面。首先我们得把这个sub函数给他实现出来,具体解法的逻辑的话,需要这么去判断:
    在这里插入图片描述
  2. 上面的这张图表示两个数在相减的过程当中每一位的一次变化关系,然后由于我们已经规定这个sub函数必须是第一个数大,第二个数小,然后第一个数去减第二个数。这也就同时意味着当指向第二个数的指针在不断移位的时候移到尽头了,但第一个数他还有余量。所以说在依次相减的过程之后,接下来就是把第一个数余下的部分给他再放到新数组当中。在这个过程当中仍然需要保持之前的借位状态,因为那个t仍然是会产生影响的,总的sub函数实现过程如下:
void sub(char* arr1, int sz1, char* arr2, int sz2)
{
    int t=0;
    int i=sz1-1;
    int j=sz2-1;
    while(i>=0 && j>=0)
    {
        if ((arr1[i]-'0')-(arr2[j]-'0')-t>=0)
        {
            ans[k++]=(arr1[i]-'0')-(arr2[j]-'0')-t+'0';
            t=0;
        }
        else
        {
            ans[k++]=(arr1[i]-'0')-(arr2[j]-'0')+10-t+'0';
            t=1;
        }
        i--;
        j--;
    }
    while(i>=0)
    {
        if ((arr1[i]-'0')-t>=0)
        {
            ans[k++]=(arr1[i]-'0')-t+'0';
            t=0;
        }
        else
        {
            ans[k++]=(arr1[i]-'0')-t+10+'0';
            t=1;
        }
        i--;
    }
}
  1. 最后还需要注意一点的是,在两个数相减的过程当中,有可能在最开头高位会出现前导0的情况,这个也需要特别去处理一下。相减的结果的高位也就意味着结果数组的右边(为我把结果的数据往数组里面放的时候,是从左往右放的),所以说只需要对结果数组ans的右边界去进行一些稍微处理就可以,去判断一下,如果说当前元素为字符0的话,就把这个k给他左移一位,并且要把这个字符零改成斜杠0,毕竟从形式语法上来说还是个字符串。
while(k>0 && ans[k-1]=='0')
{
    ans[k-1]='\0';
    k--;
}
  1. 然后最后的话,这个结果数组由于数据是从左往右放的,这也就意味着数组的左边是个位,然后是十位这么一直上去,那么在打印字符数组的时候,呈现出来的样子,要求我们必须要把数字的高位放在前面,所以说需要把这个数组给他翻转一下。
void reverse (char* arr, int l ,int r)
{
    while(l<r)
    {
        char tmp=arr[l];
        arr[l]=arr[r];
        arr[r]=tmp;
        l++;
        r--;
    }
}

reverse(ans,0,k-1);

经典例题

luck
在这里插入图片描述

#include <stdio.h>
#include <string.h>
#define N 100010
char num1[N];
char num2[N];
char ans[N];
int k;
void reverse (char* arr, int l ,int r)
{
    while(l<r)
    {
        char tmp=arr[l];
        arr[l]=arr[r];
        arr[r]=tmp;
        l++;
        r--;
    }
}
//比较两个数哪个数大,第一个大返回1, 第二个大返回2,相等就返回0
int cmp(int sz1, int sz2)
{
    if(sz1>sz2)
    {
        return 1;
    }
    else if (sz1<sz2)
    {
        return 2;
    }
    else
    {
        for (int i=0;i<sz1;i++)
        {
            if (num1[i]>num2[i])
            {
                return 1;
            }
            else if (num1[i]<num2[i])
            {
                return 2;
            }
        }
        return 0;
    }
}
void sub(char* arr1, int sz1, char* arr2, int sz2)
{
    int t=0;
    int i=sz1-1;
    int j=sz2-1;
    while(i>=0 && j>=0)
    {
        if ((arr1[i]-'0')-(arr2[j]-'0')-t>=0)
        {
            ans[k++]=(arr1[i]-'0')-(arr2[j]-'0')-t+'0';
            t=0;
        }
        else
        {
            ans[k++]=(arr1[i]-'0')-(arr2[j]-'0')+10-t+'0';
            t=1;
        }
        i--;
        j--;
    }
    while(i>=0)
    {
        if ((arr1[i]-'0')-t>=0)
        {
            ans[k++]=(arr1[i]-'0')-t+'0';
            t=0;
        }
        else
        {
            ans[k++]=(arr1[i]-'0')-t+10+'0';
            t=1;
        }
        i--;
    }
}
int main()
{
    scanf("%s %s",num1,num2);
    int sz1=strlen(num1);
    int sz2=strlen(num2);
    if (cmp(sz1,sz2)==1)
    {
        sub(num1,sz1,num2,sz2);
    }
    else if (cmp(sz1,sz2)==2)
    {
        sub(num2,sz2,num1,sz1);
        printf("-");
    }
    else
    {
        printf("0\n");  
        return 0;
    }
    while(k>0 && ans[k-1]=='0')
    {
        ans[k-1]='\0';
        k--;
    }
    reverse(ans,0,k-1);
    printf("%s\n",ans);
    return 0;
}

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

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

相关文章

《面试1v1》java反射

我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 面试官&#xff1a; 你好&#xff0c;请问你对 Java 反射有了解吗&#xff1f; 候选人&#xff1a; 是的&#xff0c;我了解一些。 面试官&#xff1a; 那你能简单…

离散数学集合论

集合论 主要内容 集合基本概念 属于、包含幂集、空集文氏图等 集合的基本运算 并、交、补、差等 集合恒等式 集合运算的算律&#xff0c;恒等式的证明方法 集合的基本概念 集合的定义 集合没有明确的数学定义 理解&#xff1a;由离散个体构成的整体称为集合&#xff0c…

【五一创作】【Midjourney】Midjourney 连续性人物创作 ② ( 获取大图和 Seed 随机种子 | 通过 seed 随机种子生成类似图像 )

文章目录 一、获取大图和 Seed 随机种子二、通过 seed 种子生成类似图像 一、获取大图和 Seed 随机种子 注意 : 一定是使用 U 按钮 , 在生成的大图的基础上 , 添加 信封 表情 , 才能获取该大图的 Seed 种子编码 ; 在上一篇博客生成图像的基础上 , 点击 U3 获取第三张图的大图 ;…

电子数据取证之宝塔面板

一、宝塔面板介绍 1、官网bt.com&#xff0c;是提升运维效率的服务器管理软件&#xff0c;支持一键WAMP/LAMP/LNMP等100多项服务器管理功能&#xff1b;是跨平台的软件&#xff0c;同时支持Windows和Linux。开源永久免费。提高工作效率&#xff0c;对小白比较友好。 2、怎么看服…

【网络socket编程----预备知识和UDP服务器模拟实现】

文章目录 一、预备知识1.1 理解IP地址和端口号1.2 认识TCP协议和UDP协议1.3 网络字节序1.4 socket编程接口和sockaddr结构 二、封装 UdpSocket 一、预备知识 1.1 理解IP地址和端口号 众所周知&#xff0c;每台主机都有一个IP地址。而主机和主机之间通信&#xff0c;也需要依赖…

对比学习论文阅读:CoCLR算法笔记

标题&#xff1a;Self-supervised Co-training for Video Representation Learning 会议&#xff1a;NIPS2020 论文地址&#xff1a;https://dl.acm.org/doi/abs/10.5555/3495724.3496201 官方代码&#xff1a;https://www.robots.ox.ac.uk/~vgg/research/CoCLR/ 作者单位&…

软考算法-排序篇-上

数据排序 一&#xff1a;故事背景二&#xff1a;直接插入排序2.1 概念2.2 画图表示2.3 代码实现2.4 总结提升 三&#xff1a;希尔排序3.1 概念3.2 画图表示3.3 代码实现3.4 总结提升 四&#xff1a;直接选择排序4.1 概念4.2 画图表示4.3 代码实现4.4 总结提升 五&#xff1a;堆…

组播PIM协议

PIM&#xff08;Protocol Independent Multicast&#xff09;称为协议无关组播&#xff08;组播分发树&#xff09;。这里的协议无关指的是与单播路由协议无关&#xff0c;即PIM不需要维护专门的单播路由信息。作为组播路由解决方案&#xff0c;它直接利用单播路由表的路由信息…

LeetCode:142. 环形链表 II

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 题解目录 一、&#x1f331;[142. 环形链表 II](https://leetcode.cn/problems/linked-l…

瑞吉外卖:后台系统登录功能

文章目录 需求分析代码开发创建实体类导入返回结果类Rcontroller、service与mapperlogin.html 需求分析 点击登录按钮后&#xff0c;浏览器以POST方式向employee/login提交username和password&#xff0c;服务器经过处理后向浏览器返回某种格式的数据&#xff0c;其中包含&…

Java SE(十一)之异常处理(Exception)

文章目录 异常概述1.什么是异常&#xff1f;2.为什么要异常&#xff1f; 异常体系及分类1.运行时异常2.编译时异常 异常处理1.JVM默认处理方案2.try…catch…3.throw & throws&#xff08;1&#xff09;抛出异常throw&#xff08;2&#xff09;声明异常throws&#xff08;3…

Android Studio制作手机App:通过手机蓝牙(Bluetooth)与STM32上的低功耗蓝牙(HC-42)连接通信,实现手机端对单片机的控制。

背景&#xff1a; 本文的内容是针对单片机蓝牙模块&#xff08;HC-42&#xff09;开发的手机App。在这之前&#xff0c;我想先声明一点&#xff0c;手机与手机间的蓝牙连接方式”与“手机与HC间的蓝牙连接方式”是不一样的。原因就是手机搭配的是“经典蓝牙”模块&#xff0c;…

HTML【前端基础】

目录 1.HTML 结构 1.1 HTML 标签 1.2 HTML 文件基本结构 1.3 标签层次结构 1.4 快速生成代码框架 2.HTML 常见标签 2.1 注释标签 2.2 标题标签: h1-h6 2.3 段落标签&#xff1a;p 2.4 换行标签: br 2.5 格式化标签 2.6 图片标签: img 2.7 超链接标签: a 2.8 表格…

Android Java 音频采集 AudioRecord

在 Android Java 应用中&#xff0c;一般用 AudioRecord 管理从平台的音频输入设备采集音频数据所需的资源。音频采集和音频播放密切关系&#xff0c;Android 系统中 Java AudioRecord 和 AudioTrack 在许多方面&#xff0c;都有着很高的相似性&#xff0c;无论是代码的目录组织…

java基础知识——25.异常

这篇文章&#xff0c;我们来讲一下java的异常体系 目录 1.异常概述 2 java的异常继承体系 2.1 编译时异常 2.2 运行时异常 2.3 底层原理 2.4 异常的作用 3.异常的处理方式 3.1 JVM默认的处理方式 3.2 自己处理&#xff08;捕获异常&#xff09; 3.2.1自己处理的4个问…

端到端NVMe?| NVMe-OF或FC-NVMe

声明 主页&#xff1a;元存储的博客_CSDN博客 依公开知识及经验整理&#xff0c;如有误请留言。 个人辛苦整理&#xff0c;付费内容&#xff0c;禁止转载。 内容摘要 前言 NVMe全称是Nonvolatile Memory Express&#xff08;非易失性内存标准&#xff09;&#xff0c;在它首次…

( 字符串) 647. 回文子串 ——【Leetcode每日一题】

❓647. 回文子串 难度&#xff1a;中等 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xff0c;即使…

JSP 的本质原理解析:“编写的时候是JSP,心里想解读的是 java 源码“

JSP 的本质原理解析&#xff1a;“编写的时候是JSP&#xff0c;心里想解读的是 java 源码” 文章目录 JSP 的本质原理解析&#xff1a;"编写的时候是JSP&#xff0c;心里想解读的是 java 源码"每博一文案1. JSP 概述2. 第一个 JSP 程序3. JSP 的本质就是 Servlet4. J…

appium的手动安装步骤教程及appium-doctor报错解决集合

前言 相信你不少软件测试行业小伙伴应该在用npm安装appium或者是cpm安装appium途中也碰到下面一些报错吧&#xff0c;接下来Darren洋教你改为手动安装appium吧&#xff01;整理不易&#xff0c;请点赞加关注后查看。 一、安装Node.js 下载地址&#xff1a; Previous Releases …