加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

大数的乘法,如何捕获溢出

发布时间:2020-12-14 04:56:42 所属栏目:大数据 来源:网络整理
导读:我正在寻找一个高效的(可选标准,优雅和容易实现)解决方案来乘以相对大的数字,并将结果存储到一个或几个整数: 假设我有两个64位整数这样声明: uint64_t a = xxx,b = yyy; 当我做a * b,如何检测操作是否导致溢出,在这种情况下存储进位的地方? 请注意,
我正在寻找一个高效的(可选标准,优雅和容易实现)解决方案来乘以相对大的数字,并将结果存储到一个或几个整数:

假设我有两个64位整数这样声明:

uint64_t a = xxx,b = yyy;

当我做a * b,如何检测操作是否导致溢出,在这种情况下存储进位的地方?

请注意,我不想使用任何大数字库,因为我有存储数字的方式的约束。

谢谢

解决方法

检测:

x = a * b;
if (a != 0 && x / a != b) {
    // overflow handling
}

编辑:固定除以0(谢谢马克!)

计算进位相当牵连。一种方法是将两个操作数拆分为半字,然后将long multiplication应用于半字:

uint64_t hi(uint64_t x) {
    return x >> 32;
}

uint64_t lo(uint64_t x) {
    return ((1L << 32) - 1) & x;
}

void multiply(uint64_t a,uint64_t b) {
    // actually uint32_t would do,but the casting is annoying
    uint64_t s0,s1,s2,s3; 

    uint64_t x = lo(a) * lo(b);
    s0 = lo(x);

    x = hi(a) * lo(b) + hi(x);
    s1 = lo(x);
    s2 = hi(x);

    x = s1 + lo(a) * hi(b);
    s1 = lo(x);

    x = s2 + hi(a) * hi(b) + hi(x);
    s2 = lo(x);
    s3 = hi(x);

    uint64_t result = s1 << 32 | s0;
    uint64_t carry = s3 << 32 | s2;
}

要看到没有一个部分和本身可以溢出,我们认为最坏的情况:

x = s2 + hi(a) * hi(b) + hi(x)

令B = 1<<我们有

x <= (B - 1) + (B - 1)(B - 1) + (B - 1)
              <= B*B - 1
               < B*B

我相信这将工作 – 至少它处理Sjlver的测试用例。除此之外,它是未经测试的(甚至可能不编译,因为我现在没有一个C编译器)。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读