当前位置:首页 > 题解目录 > 正文内容

【题解】大整数减法

亿万年的星光5年前 (2021-05-02)题解目录17295

【题目描述】

求两个大的正整数相减的差。

【输入】

共2行,第1行是被减数a,第2行是减数b(a > b)。每个大整数不超过200位,不会有多余的前导零。

【输出】

一行,即所求的差。

【输入样例】

9999999999999999999999999999999999999

9999999999999

【输出样例】

9999999999999999999999990000000000000


【参考答案】


1.基础版:char数组

#include<iostream>  
#include<cstring>  
#include<string>  
using namespace std;  

int main()  
{  
    char str1[256],str2[256],temp[256];  
    int a[256],b[256],c[256];  
    int lena,lenb,lenc;  
    int i;  

    memset(a,0,sizeof(a));  
    memset(b,0,sizeof(b));  
    memset(c,0,sizeof(c));  

    cin>>str1;//输入被减数  
    cin>>str2;//输入减数  

    lena=strlen(str1);  
    lenb=strlen(str2);  

    // 修正:明确判断被减数小于减数(长度更小,或长度相等且字典序更小)
    bool is_negative = false;
    if( (lena < lenb) || (lena == lenb && strcmp(str1, str2) < 0) )  
    {  
        // 交换被减数和减数
        strcpy(temp, str1);  
        strcpy(str1, str2);  
        strcpy(str2, temp);  
        is_negative = true; // 标记结果为负
    }  

    // 重新获取交换后的长度
    lena = strlen(str1);  
    lenb = strlen(str2);  

    // 被减数str1存入数组a(逆序存储,a[1]对应个位)
    for(i = 0; i <= lena - 1; i++)  
        a[lena - i] = str1[i] - '0';  
    // 减数str2存入数组b(逆序存储,b[1]对应个位)
    for(i = 0; i <= lenb - 1; i++)  
        b[lenb - i] = str2[i] - '0';  

    // 高精度减法核心:逐位相减并处理借位
    i = 1;  
    while(i <= lena || i <= lenb)  
    {  
        if(a[i] < b[i])  
        {  
            a[i] += 10; // 借位,当前位加10
            a[i + 1]--; // 高位减1
        }  
        c[i] = a[i] - b[i]; // 对应位相减结果存入c
        i++;  
    }  
    lenc = i;  

    // 删除前导0(保留至少一位,避免全0情况无输出)
    while((c[lenc] == 0) && (lenc > 1))  
        lenc--;  

    // 输出符号(若为负)
    if(is_negative)  
        cout << "-";  

    // 特殊处理:两数相等时,lenc最终为1,c[1]=0,正常输出0
    // 倒序输出结果(从高位到低位)
    for(i = lenc; i >= 1; i--)  
        cout << c[i];  

    cout << endl;  
    return 0;  
}



2.string版本

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

int main() {
    string s1, s2;
    cin >> s1 >> s2;
    bool neg = false;

    // 交换处理:确保s1 >= s2
    if (s1.size() < s2.size() || (s1.size() == s2.size() && s1 < s2)) {
        swap(s1, s2);
        neg = true;
    }

    // 逆序处理(方便低位对齐计算)
    reverse(s1.begin(), s1.end());
    reverse(s2.begin(), s2.end());
    
    string res;
    res.resize(s1.size()); //初始化 
    int borrow = 0; // 借位标记

    // 逐位相减
    for (int i = 0; i < s1.size(); i++) {
        int num1 = s1[i] - '0';
        int num2;
        // 判断是否超出s2长度
        if (i < s2.size()) {
            num2 = s2[i] - '0';
        } else {
            num2 = 0;
        }
        
        int sub = num1 - num2 - borrow;
        borrow = 0;
        if (sub < 0) {
            sub += 10;
            borrow = 1;
        }
        res[i] = sub + '0';
    }

    // 第一步:找到第一个非0的最高位(逆序后的末尾方向)
    int len = res.size(); // 有效长度初始化为总长度
    while (len > 1 && res[len - 1] == '0') {
        len--; // 仅修改有效长度标记,不删除字符串内容
    }
    // 恢复正序(仅处理有效长度内的字符)
    reverse(res.begin(), res.begin() + len);
    // 输出结果:仅输出有效长度内的字符(跳过无效的前导0)
    if (neg) cout << "-";
    // 从res的末尾(原有效部分的起始)开始输出,长度为valid_len
    for (int i = res.size() - len; i < res.size(); i++) {
        cout << res[i];
    }
    cout << endl;

    return 0;
}


    扫描二维码推送至手机访问。

    版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

    分享给朋友:

    相关文章

    【题解】踩方格

    【题目描述】有一个方格矩阵,矩阵边界在无穷远处。我们做如下假设:a、每走一步时,只能从当前方格移动一格,走到某个相邻的方格上;b、走过的格子立即塌陷无法再走第二次;c、只能向北、东、西三个方向走;请问...

    【题解】区间数位个数

    区间数位个数(digit.cpp)【描述】给定整数n和整数k,求出1~n中所有数的每一位数字中,出现数字k的次数。【输入】第一行是两个个整数n和k【输出】一个整数表示答案。【样例输入输出】light....

    【题解】人民币问题

    【题目描述】给出任意的人民币(>10 元)的整币兑换成 5 元、2 元和 1 元币值(要求三种币值均有)的方法有多少种。【输入描述】输入任意的人民币(>10 元)的整币 100,50,20...

    猴子吃桃

    【题目描述】猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。 第二天早上又将剩下的桃子吃掉一半,又多吃一个。以后每天早上都吃了前一天剩下的一半零一个。到第N天早上想再吃时...

    【题解】队列问题

    【题解】队列问题

    4.队列问题(lru.cpp)【题目描述】有一个大小为n的页面缓存队列,初始为空,当计算机访问页面时,若缓存队列没有该页面,则加入到缓存队列中,若队列已满,则将删除访问时间最远的页面。有Q次询问,每次...

    【题解】木材加工

    【题目描述】 木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头(木头有可能有剩余),需要得到的小段的数目是事先给定的,切割时希望得到的小段越长越好。   ...