在两个大整数相乘期间捕获和计算溢出 [英] Catch and compute overflow during multiplication of two large integers

查看:26
本文介绍了在两个大整数相乘期间捕获和计算溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种有效(可选标准、优雅且易于实现)的解决方案来乘以相对较大的数字,并将结果存储到一个或多个整数中:

I am looking for an efficient (optionally standard, elegant and easy to implement) solution to multiply relatively large numbers, and store the result into one or several integers :

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

Let say I have two 64 bits integers declared like this :

uint64_t a = xxx, b = yyy; 

当我执行 a * b 时,如何检测操作是否导致溢出并在这种情况下将进位存储在某处?

When I do a * b, how can I detect if the operation results in an overflow and in this case store the carry somewhere?

请注意,我不想使用任何大型库,因为我对存储数字的方式有限制.

Please note that I don't want to use any large-number library since I have constraints on the way I store the numbers.

推荐答案

1.检测溢出:

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

固定除法 0(感谢 Mark!)

Fixed division by 0 (thanks Mark!)

<强>2.计算进位相当复杂.一种方法是将两个操作数拆分为半字,然后将 长乘法 应用于一半-单词:

2. Computing the carry is quite involved. One approach is to split both operands into half-words, then apply long multiplication to the half-words:

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

uint64_t lo(uint64_t x) {
    return ((1ULL << 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;
}

为了确保部分和本身不会溢出,我们考虑最坏的情况:

To see that none of the partial sums themselves can overflow, we consider the worst case:

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

B = 1 <<<32.然后我们有

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

我相信这会起作用 - 至少它可以处理 Sjlver 的测试用例.除此之外,它未经测试(甚至可能无法编译,因为我手头没有 C++ 编译器了).

I believe this will work - at least it handles Sjlver's test case. Aside from that, it is untested (and might not even compile, as I don't have a C++ compiler at hand anymore).

这篇关于在两个大整数相乘期间捕获和计算溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆