高精度四则运算的C++代码实现

应该注释还算清楚,适合有一定水平的入门者。基础设计来源于crq

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N], b[N], c[N];

//字符串类型转换为数组,并且倒过来
void stringToArr(string s, int a[])
{
    int len = s.length();
    //倒过来进行赋值
    for (int i = 0; i < len; i++)
    {
        a[i] = s[len - i - 1] - '0';
    }
}

//初始化字符串转换为数组
void init(string s1, string s2)
{
    //清0,全局变量只有第一次是0
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    //将其转为数字串,并倒过来
    stringToArr(s1, a);
    stringToArr(s2, b);
}

//数组转换为字符串,并且倒过来
string arrToString(int a[], int n)
{
    string s = "";
    //倒过来进行字符的还原
    for (int i = n - 1; i >= 0; i--)
    {
        s += (char)(a[i] + '0');
    }
    return s;
}

//两数比较,大于等于返回true
bool cmp(string a, string b)
{
    //位数不等,位数大的数大
    if (a.length() != b.length())
    {
        return a.length() > b.length();
    }
    //位数相等字典序大小即大小关系
    return a >= b;
}

//加法
string add(string s1, string s2)
{
    //先把s1和s2初始化到ab数组里
    init(s1, s2);
    //长度为两数最大的那个数
    int len = max(s1.length(), s2.length());
    //进位
    int step = 0;
    for (int i = 0; i < len; i++)
    {
        //当前位就是两数相加及进位的个位
        c[i] = (a[i] + b[i] + step) % 10;
        //当前位就是两数相加及进位的十位
        step = (a[i] + b[i] + step) / 10;
    }
    //进位不为0,所以要多一位
    if (step != 0)
        c[len++] = step;
    return arrToString(c, len);
}

//减法,只能大减小
string sub(string s1, string s2)
{
    //先把s1和s2初始化到ab数组里
    init(s1, s2);
    for (int i = 0; i < s1.length(); i++)
    {
        //小于就借位
        if (a[i] < b[i])
        {
            a[i] += 10;
            a[i + 1]--;
        }
        //进行除法
        c[i] = a[i] - b[i];
    }
    //s1是大数,所以他的长度就是ans的长度
    int m = s1.length();
    //去除前导0
    while (m > 0 && c[m - 1] == 0)m--;
    //相等结果为0要返回0
    if (m == 0)return "0";
    //把c数组转换为string类型输出,m作为位数传递
    return arrToString(c, m);
}

//乘法
string mul(string s1, string s2)
{
    //先把s1和s2初始化到ab数组里
    init(s1, s2);
    for (int j = 0, i; j < s2.length(); j++)
    {
        //进位为step
        int step = 0;
        for (i = 0; i < s1.length(); i++)
        {
            //就是列乘法计算,直接加进去目标位
            c[i + j] += a[i] * b[j] + step;
            //有可能产生进位,需要保存
            step = c[i + j] / 10;
            //目标位是一位数
            c[i + j] = c[i + j] % 10;
        }
        //最终进位还是空的,直接给进位吧
        c[i + j] = step;
    }
    //最终可能有两个总长的位数
    int m = s1.length() + s2.length();
    //去除前导0
    while (m > 1 && c[m - 1] == 0)m--;
    return arrToString(c, m);
}

//除法,返回余数,c是商
string div(string a, string b, string &c)
{
    //remainder的缩写,代表余数,也就是当前的被除数
    string rem = "";
    //c有可能会被操作了,清空一下
    c = "";
    for (int i = 0; i < a.length(); i++)
    {
        //余数为0,就是当前一位。否则加上当前位
        if (rem == "0")rem = a[i];
        else rem = rem + a[i];
        int t = 0;
        //如果被除数比除数大,进行减法,t最大也是9
        while (cmp(rem, b))
        {
            rem = sub(rem, b);
            t++;
        }
        //c还是空且t是0,直接进行下一次循环,解决了商的前导0
        if (c == "" && t == 0)continue;
        //商加上求出的当前位
        c = c + char(t + '0');
    }
    return rem;
}
int main()
{
    string a,b,c;
    while(cin >> a >> b)
    {
        //加法
        cout << add(a,b) << "\n";
        //减法
        cout << sub(a,b) << "\n";
        //乘法
        cout << mul(a,b) << "\n";
        //除法使用,依次输出商和余数
        string d = div(a, b, c);
        cout << c << "\n" << d << "\n";
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BobHuang/p/12264376.html
今日推荐