C ++ Tools package from Tarsus Calculator (ten thousand decimal achieve)

What is 大数计算, for example, allows you to calculate a multiplication m*n, which m, nare a few hundred Place long \ Color {red} hundreds length of data, and the need to maintain the accuracy of the original data, then the basic data typesint,long longcertainly not, already more than the range.

In Java, there are large numbers tools BigIntegerand some large numbers handler class, in Pythonthe language itself is not limited to support data length is calculated, and the C++in itself does not support.

Blogger after another made the wheel a few times now since the package to achieve a large number arithmetic tools, if there are good ideas please share.

1, input data, output in the form of

Input and output are numeric string stringtype.

2, calculation principle (ten thousand decimal)

I used 万进制, 逢万进一.
Is entered numeric string, such as " 12345601230009", and then converted into int array intsNum[4, 9, 123, 3456, 12], intsNum[0]represents the length of the array, intsNum[1]=9represents the first stage in the numeric string "0999" , intsNum[2]=123the second stage array represents 0123, it representsintsNum[3]=3456 the first array three sections 3456, intsNum[4]=12indicating the array of the fourth segment12

int array multiplication rule
Here Insert Picture Description

#include <iostream>
#include <string.h>
#include <string>
using namespace std;

//将两个数组相加,并且结果存放子啊num3
//数组示例[4,123,0,1234,9],4表示长度,真正表示是的值为 ‘9 1234 0000 0123’
void add(int* num1, int* num2, int* num3, int maxLen) {
    if (num1[0] < num2[0]) {
        //维持num1的长度 >= num2的长度
        add(num2, num1, num3, maxLen);
        return;
    }
    memset(num3, 0, maxLen);
    //1、将num1复制到num3中
    for (int i = 0; i <= num1[0]; ++i) {
        num3[i] = num1[i];
    }
    //2、将num2按位加到num3上
    for (int i = 1; i <= num2[0]; ++i) {
        //num1[i]、num2[i]相加,并且加入低位的进位值
        num3[i] += num2[i];
        //num3[i] 逢万进位
        num3[i + 1] += num3[i] / 10000;
        num3[i] %= 10000;
    }
    //3、考虑num3是否会产生最高位的进位
    int carryIndex = num2[0] + 1;
    while (num3[carryIndex] > 9999) {
        num3[carryIndex + 1] += num3[carryIndex] / 10000;
        num3[carryIndex++] %= 10000;
    }
    //更新num3的长度
    if (carryIndex > num3[0] && num3[carryIndex] > 0) {
        num3[0] = carryIndex;
    }
}

//将两个数组相乘,并且结果存放子啊num3
//数组示例[4,123,0,1234,9],4表示长度,真正表示是的值为 ‘9 1234 0000 0123’
void mutli(int* num1, int* num2, int* num3, int maxLen) {
    memset(num3, 0, maxLen);
    //1、对num1、num2进行相乘
    for (int i = 1; i <= num2[0]; ++i) {
        for (int j = 1; j <= num1[0]; ++j) {
            //num1的第j位 与 num2的第i位相乘,应该放在num3的 第i + j - 1位上,画一个多位数相乘算术式可知
            num3[i + j - 1] += num1[i] * num2[j];
            if (num3[i + j - 1] > 9999) {
                //num3[i + j - 1] 逢万进位
                num3[i + j] += num3[i + j - 1] / 10000;
                num3[i + j - 1] %= 10000;
            }
        }
    }
    //2、检查num3是否有进位,注意长度为m、n位的两个数相乘结果长度不会超过 m + n
    //初始化num3的长度为 num1、num2之和
    num3[0] = num1[0] + num2[0];
    for (int i = 1; i < num3[0]; ++i) {
        if (num3[i] > 10000) {
            num3[i + 1] += num3[i] / 10000;
            num3[i] %= 10000;
        }
    }
    //如果最高位为0,说明结果小于
    if (num3[num3[0]] == 0) {
        num3[0] -= 1;
    }
}

//将数字字符串转成int数组,比如"12304560001",转换结果为[3, 1, 456, 123]
void strToInts(const string &num, int* numInts, int maxLen) {
    memset(numInts, 0, maxLen);
    for (int i = (int)num.size() - 1; i >= 0; ) {
        int tempNum = 0, j = 0, weight = 1;
        //取出四位转成整形
        while (i >= 0 && j++ < 4) {
            tempNum +=  (num[i--] - '0') * weight;
            weight *= 10;
        }
        numInts[++numInts[0]] = tempNum;
    }
}

//将int数组转换会字符串类型
string intsToStr(int* numInts) {
    if (numInts[0] == 0) {
        return  "0";
    }
    //最高位不需要补零
    string resStr = to_string(numInts[numInts[0]]);
    //注意访问顺序,是从高->低
    for (int i = numInts[0] - 1; i >= 1; --i) {
        string tempStr = "";
        //中间不足四位需要补零
        if (numInts[i] < 1000) {
            tempStr += '0';
        }
        if (numInts[i] < 100) {
            tempStr += '0';
        }
        if (numInts[i] < 10) {
            tempStr += '0';
        }
        tempStr += to_string(numInts[i]);
        resStr.append(tempStr);
    }
    return resStr;
}

//大数乘法(暂时支持正整形,浮点计算、负号保留计算以后更新)
string bigNumMutli(const string &num1, const string &num2) {
    //没有万进制最大容纳9999,因此100位万进制大约可容纳400长度的计算(乘法最大支持200位左右)
    int intsNum1[101] = { 0 }, intsNum2[101] = { 0 }, intsSum[101] = { 0 };
    strToInts(num1, intsNum1, 101);
    strToInts(num2, intsNum2, 101);
    mutli(intsNum1, intsNum2, intsSum, 101);
    return intsToStr(intsSum);
}

//大数加法(暂时支持正整形,浮点计算、负号保留计算以后更新)
string bigNumAdd(const string &num1, const string &num2) {
    //没有万进制最大容纳9999,因此100位万进制大约可容纳400长度的计算
    int intsNum1[101] = { 0 }, intsNum2[101] = { 0 }, intsSum[101] = { 0 };
    strToInts(num1, intsNum1, 101);
    strToInts(num2, intsNum2, 101);
    add(intsNum1, intsNum2, intsSum, 101);
    return intsToStr(intsSum);
}

int main() {
    string a, b;
    //scanf返回值为正确输入数据的变量个数,当一个变量都没有成功获取数据时,此时返回-1
    while (cin >> a >> b) {
        cout << "两者乘积:" + bigNumMutli(a, b) << endl;
        cout << "两者求和:" + bigNumAdd(a, b) << endl;
    }
    return 0;
}
Released 1008 original articles · won praise 272 · Views 230,000 +

Guess you like

Origin blog.csdn.net/qq_41855420/article/details/104709200