数学问题——大数处理

Posted 牧空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数学问题——大数处理相关的知识,希望对你有一定的参考价值。

虽然也算不上传统的数学问题,但是在计算的过程中是需要处理的,一般会涉及四则运算,那么就算作是数学问题吧。

解法

预设:

  • 使用整型数组存储大数
  • 最大长度不超过1000
  • 使用十进制
  • 使用逆序存储数值,即number[0]为大数的最低位

对于上述预设转换成如下代码

#define WEIGHT 10
#define MAX_LEN 1000
struct BigNumber{
	int number[MAX_LEN];
	int len;
	BigNumber(){
		memset(number, 0, sizeof(number));
	}	
};

其中,将字符串转换为大数存储在数组中和大数的比较在此处不作展开


其中加减乘都是从低位向高位运算的,所以具有一定的相似性

加法(非负整数)

BigNumber add(BigNumber a, BigNumber b)
{
    BigNumber c = BigNumber();
    int i = 0;
    for (; i < a.len || i < b.len; i++)
    {
        c.number[i] += a.number[i] + b.number[i];
        if (c.number[i] >= WEIGHT)
        {
            c.number[i + 1] = 1;
            c.number[i] = c.number[i] % WEIGHT;
        }
    }
    c.len = c.number[i] != 0 ? i + 1 : i;
    return c;
}

减法

BigNumber sub(BigNumber a, BigNumber b)
{
    BigNumber c = BigNumber();
    // b > a, c为负
    if (compare(a, b) == -1)
    {
        c.sign = false;
        BigNumber temp = b;
        b = a;
        a = temp;
    }
    int i = 0;
    for (; i < a.len || i < b.len; i++)
    {
        //向高位借位
        if (a.number[i] < b.number[i])
        {
            a.number[i + 1]--;
            a.number[i] += WEIGHT;
        }
        c.number[i] = a.number[i] - b.number[i];
    }

    c.len = c.number[i] != 0 ? i + 1 : i;
    return c;
}

乘法

BigNumber multi(BigNumber a, BigNumber b)
{
    BigNumber c;
    for (int i = 0; i < a.len; i++)
    {
        for (int j = 0; j < b.len; j++)
        {
            c.number[i + j] += a.number[i] * b.number[j];
            c.number[i + j + 1] += c.number[i + j] / WEIGHT;
            c.number[i + j] = c.number[i + j] % WEIGHT;
        }
    }
    c.len = a.len + b.len;
    c.sign = a.sign == b.sign;
    while (c.len > 0 && c.number[c.len] == 0) //删除前导0
        c.len--;
    return c;
}

除法

除法相对前面几个稍微难一些,这里使用的是模拟减法。
就是从高位开始,循环减去(除数*基数^x),直至小于被除数,此过程中,商对应位的值累加,
如此这般,直至x=0。

void simulation(BigNumber &a, BigNumber b)
{
    int flag = 0, i = 0;
    flag = compare(a, b);
    if (flag == 0)
    {
        a.len = 0;
        return;
    }
    if (flag == 1) //大于
    {
        for (; i < a.len; i++)
        {
            if (a.number[i] < b.number[i]) //若不够向上借位
            {
                a.number[i + 1]--;
                a.number[i] += 10;
            }
            a.number[i] -= b.number[i];
        }
        while (a.len > 0 && a.number[a.len - 1] == 0) //删除前导0
            a.len--;
        return;
    }
}



BigNumber divide(BigNumber a, BigNumber b)
{
    BigNumber c;
    c.len = a.len - b.len + 1; //商的最大位数

    for (int i = c.len; i > 0; i--)
    {
        BigNumber temp;
        copy2temp(b, temp, i);
        while (compare(a, temp) >= 0)
        {
            c.number[i - 1]++;
            simulation(a, temp);
        }
    }
    while (c.len > 0 && c.number[c.len - 1] == 0) //删除前导0
        c.len--;
    return c;
}

以上是关于数学问题——大数处理的主要内容,如果未能解决你的问题,请参考以下文章

数学问题——进制转换

刷题常用之大数类数学类

求解Catalan数,(大数相乘,大数相除,大数相加)

剪绳子问题 之动态规划 及 大数越界情况下的求余问题

UVA11554 Hapless Hedonism数学计算+大数

统计和数学中常见的定理汇总 | 大数定律 | 中心极限定理