【Code pratice】—— 大数乘法

D a t e : 2022 − 10 − 07 \color{33CCFF}{Date:2022-10-07} Date20221007

L a s t \color{33CCFF}{Last} Last n i g h t \color{33CCFF}{night} night a \color{33CCFF}{a} a f e w \color{33CCFF}{few} few e x t r a \color{33CCFF}{extra} extra m i n u t e s \color{33CCFF}{minutes} minutes p r e p a r a t i o n , \color{33CCFF}{preparation,} preparation, f e w e r \color{33CCFF}{fewer} fewer h o u r s \color{33CCFF}{hours} hours o f \color{33CCFF}{of} of t r o u b l e \color{33CCFF}{trouble} trouble t o d a y ! \color{33CCFF}{today!} today!

🥠1. 大数乘法🥠

🍖题目🍖

对于32位字长的机器,大约超过20亿,用int类型无法表示,我们可以选择int64类型,但无论怎么扩展,固定的整数类型总有表达的极限!如果对超级大整数进行精确运算呢?一个简单的方法就是:仅仅使用现有的类型,但是把大整数的运算化为若干个小证书的运算,即所谓:“分块法”,原理如下图
在这里插入图片描述

🍖思路🍖

本题关键在于理解分块乘法的原理,原理中的分块很好理解,乘法也很好理解,难理解的是进位

  1. 分块:按照图中的x1, x2, y1, y2对数字进行取值即可
  2. 乘法:按照图中的m1, m2, m3, m4对数字进行相乘即可
  3. 结果:图中的r1, r2, r3, r4,并不是简单的r1 = m4, r2 = m2 + m3 + m4, r3 = m1 + m2 + m3, r4 = m1的相加,因为m1 ~ m4这四个值是通过x1, x2, y1, y2组合相乘得来的,而x1, x2, y1, y2又是通过原有数值进行分块而来,所以这个相加并不简单。不简单在于这里需要回归 + 进位,可以注意到图中有每一个mn都有两个,为什么?因为它们对应分块时的前段和后段,所以rn的取值应该先回归,然后还需要对每一部分的结果进行进位
    • 回归:如果当前结果是由前段分块乘积得来,那么结果也要对应的回归到前段的队伍中,反之亦然
    • 进位:就是熟知的加法运算中的进位,如满10进1等

举个例子
X = 23, Y= 34, 分两段,以10为界

  1. 分块
    • x1 = X % 10 = 3, x2 = X / 10 = 2
    • y1 = Y % 10 = 4, y2 = Y / 10 = 3
  2. 乘法
    • m1 = x1 * y1 = 12;
    • m2 = x2 * y1 = 8;
    • m3 = x1 * y2 = 9;
    • m4 = x2 * y2 = 6;
  3. 结果
    • 回归
      1. r1 = m4(前段) = 6 / 10 = 0;
      2. r2 = m2(前段) + m3(前段) + m4(后段) = 8 / 10 + 9 / 10 + 6 % 10 = 6;
      3. r3 = m1(前段) + m2(后段) + m3(后段) = 12 / 10 + 8 % 10 + 9 % 10 = 18;
      4. r4 = m1(后段) = 12 % 10 = 2;
    • 进位
      1. r4:通过后段获取,本身就是相当于个位数,不需要进位
      2. r3:将大于后段范围(前段值)的部分进位到r2,自身保留后段
        r2 = r2 + r3 / 10 = 6 + 1 = 7
        r3 = r3 % 10 = 18 % 10 = 8
      3. r2:将大于后段范围(前段值)的部分进位到r1,自身保留后段
        r1 = r1 + r2 / 10 = 0 + 6 / 10 = 0
        r2 = r2 % 10 = 6 % 10 = 6
      4. r1:通过前段获取,本身相当于最大位,与后面进位上来的结果值相加即可
      5. 最后结果为r1r2r3r4 = 0782

🍖代码🍖

void MultiLargeNumbers(int i_uXnum, int i_uYnum, int i_uBase)
{
    vector<int> res(4, 0);
    /* 1. 获取各部分小数 */
    int x1 = i_uXnum % i_uBase;
    int x2 = i_uXnum / i_uBase;
    int y1 = i_uYnum % i_uBase;
    int y2 = i_uYnum / i_uBase;

    /* 2. 获取m1, m2, m3, m4 的值 */
    int m1 = x1 * y1;
    int m2 = x2 * y1;
    int m3 = x1 * y2;
    int m4 = x2 * y2;

    /* 3. 保存r1, r2, r3, r4 的初步结果 */
    res[0] = m4 / i_uBase;
    res[1] = m2 / i_uBase + m3 / i_uBase + m4 % i_uBase;
    res[2] = m1 / i_uBase + m2 % i_uBase + m3 % i_uBase;
    res[3] = m1 % i_uBase;

    /* 4. 根据乘积,进行进位处理 */
    res[1] += res[2] / i_uBase;
    res[2] %= i_uBase;
    res[0] += res[1] / i_uBase;
    res[1] %= i_uBase;

    /* 5. 输出最后结果 */
    cout << "Final result = [" << res[0] << res[1] << res[2] << res[3] << "]" << endl;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ltd Pikashu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值