高精度加法

呐!众所周知,数据是有范围的

(Python && Java:) sorry,高精度真的可以为所欲为

高精度真的可以为所欲为

本文为博客园 ShyButHandsome的原创作品,转载请注明出处

注:右边有目录,方便快速浏览

需求原因

C++中的数据类型是有范围的

实现思路

虽然内置数据类型范围不大

但是字符串能很长啊!

我们将加数的每一位都看作是一个字符的话

那我们就得到了两个字符串

代码实现

解释都在代码里了

#include <iostream>

// EXIT_SUCCESS在stdlib库中
#include <cstdlib>

// strlen函数需要cstring库
#include <cstring>

using namespace std;

// 500+6防止数组越界
const int LENGTH_LIMIT = 5e2 + 6;

// char表示的整数 减去一个‘0’就可以得到响应整数的ascii
const int INT_CHANGER = '0';

// 个位数不能超过10
const int SINGLE_LIMIT = 10;

char stringA[LENGTH_LIMIT];
char stringB[LENGTH_LIMIT];

int invertedA[LENGTH_LIMIT];
int invertedB[LENGTH_LIMIT];
int sum[LENGTH_LIMIT];

int main(void)
{

    cin >> stringA >> stringB;

    // 倒序储存
    int lengthA = strlen(stringA);
    for (int i = 0; i < lengthA; i++)
    {
        // 由于strlen返回的长度是符合正常思维(从1开始)
        // 但我们是从0开始,所以要额外 - 1
        invertedA[i] = stringA[lengthA - i - 1] - INT_CHANGER;
    }

    int lenghtB = strlen(stringB);
    for (int i = 0; i < lenghtB; i++)
    {
        invertedB[i] = stringB[lenghtB - i - 1] - INT_CHANGER;
    }

    // 和的最大长度是a,b最大值+1
    const int MAX_LENGTH = ((lengthA < lenghtB) ? lenghtB : lengthA) + 1;

    // 进位
    int carry = 0;

    // 模拟计算
    for (int i = 0; i < MAX_LENGTH; i++)
    {
        // 对应位相加
        sum[i] = invertedA[i] + invertedB[i] + carry;
        // 记录下进位
        carry = sum[i] / SINGLE_LIMIT;
        // 进位操作
        sum[i] %= SINGLE_LIMIT;
    }

    // 这里length选择放在循环外,因为两个循环都会用到它
    // +1是因为strlen返回的数组长度是从1开始计数的
    int length = MAX_LENGTH;

    // 删除前导零(确定数字实际长度)
    // 这里取length>0,因为
    // 如果删到最后一位就必须得保留,不管它是不是0
    for (length; length > 0; length--)
    {
        if (sum[length] == 0)
        {
            // 接着处理下一位
            continue;
        }
        else
        {
            // 如果遇到一位非零就说明前导零删干净了
            // 接着删就会删去数字中的0了
            break;
        }
    }

    // 正序输出
    for (length; length >= 0; length--)
    {
        cout << sum[length];
    }

    // 额外输出一个换行
    cout << endl;

    // EXIT_SUCCESS means 0
    return EXIT_SUCCESS;
}

再给出一份用STL写的:

#include <bits/stdc++.h>

using namespace std;

int main(void)
{
    string strA, strB;
    cin >> strA >> strB;

    vector<int> numA, numB, sum;
    
    for (int i = strA.size() - 1; i >= 0; i--)
    {
        numA.push_back(strA[i] - '0');
    }
    for (int i = strB.size() - 1; i >= 0; i--)
    {
        numB.push_back(strB[i] - '0');
    }

    int carry = 0;
    for (int i = 0; i < (max(numA.size(), numB.size())); i++)
    {
        sum.push_back(carry);
        // If lenA != lenB
        sum[i] += (i > (numA.size() - 1) ? 0 : numA[i]) + (i > (numB.size() - 1) ? 0 : numB[i]);
        carry = (sum[i]) / 10;
        sum[i] %= 10;
    }

    if (carry != 0)
    {
        cout << carry;
    }

    for (int i = sum.size() - 1; i >= 0; i--)
    {
        cout << sum[i];
    }

    cout << endl;

    return 0;
}

易错点

下面是我总结出的几个易错点

每个易错点都给出了测试数据

可以利用右上角的复制按钮快速复制

没有处理进位

包括

  • 每次没有计算上次的进位啊
  • 每次没有加上上次的进位啊
  • 边界没有进位啊
  • 等等

测试数据:

输入:

56546876443156448001
56453168410002134684

输出:

113000044853158582685

删除前导零错误

测试数据:

输入 1:

11111111111111111111111111
9999999999999999999999999999999999

输出 1:

10000000011111111111111111111111110

输入 2:

0
0

输出 2:

0

STL还要注意长度不一样

输入:

350204156568812004512541458715942878921069349854678
5120132301230048014584016540526804565814706519846494321001345794503242112976563432120

输出:

5120132301230048014584016540526804916018863088658498833542804510446121034045913286798
原文地址:https://www.cnblogs.com/ShyButHandsome/p/12809662.html