64位机器上的无符号128位除法

时间:2009-12-08 22:02:21

标签: integer-division

我有一个128位数字存储为2个64位数字(“Hi”和“Lo”)。我只需要将它除以32位数。我怎么能这样做,使用CPU的本机64位操作?

(请注意,我不需要任意精度库。只需要知道如何使用本机操作进行简单划分。谢谢。)

4 个答案:

答案 0 :(得分:3)

如果使用您的架构可以处理的最大可能本机表示(64位)来存储值(128位),则在处理除法的中间结果时会遇到问题(如您已经找到的那样:)。 / p>

但是你总是可以使用SMALLER表示法。四位数的32位怎么样?这样,您可以使用本机64位操作而不会出现溢出问题。

可以找到一个简单的实现(在Delphi中)here

答案 1 :(得分:2)

如何使用CPU的本机64位操作来做到这一点?

由于需要 native 操作,因此必须使用一些内置类型或内部函数。 所有上述答案只会为您提供一般的C解决方案,这些解决方案不会编译为除法指令

大多数现代64位编译器都有一些方法可以进行128 x 64的除法。在MSVC中,使用_div128()_udiv128(),因此您只需要调用_udiv128(hi, lo, divisor, &remainder)

_div128内部函数将128位整数除以64位整数。返回值保存商,内部函数通过指针参数返回余数。 _div128是针对Microsoft的。

在Clang,GCC和ICC中,有一种__int128类型,您可以直接使用它

unsigned __int128 div128by32(unsigned __int128 x, uint64_t y)
{
    return x/y;
}

答案 2 :(得分:2)

一些c代码here

答案 3 :(得分:1)

我有一个DECIMAL结构,它由三个32位值组成:Lo32,Mid32和Hi32共计96位。

您可以轻松地将我的C代码扩展为128位,256位,512位甚至1024位除法。

// in-place divide Dividend / Divisor including previous rest and returning new rest
static void Divide32(DWORD* pu32_Dividend, DWORD u32_Divisor, DWORD* pu32_Rest)
{
    ULONGLONG u64_Dividend = *pu32_Rest;
    u64_Dividend <<= 32;
    u64_Dividend |= *pu32_Dividend;

    *pu32_Dividend = (DWORD)(u64_Dividend / u32_Divisor);
    *pu32_Rest     = (DWORD)(u64_Dividend % u32_Divisor);
}

// in-place divide 96 bit DECIMAL structure
static bool DivideByDword(DECIMAL* pk_Decimal, DWORD u32_Divisor)
{
    if (u32_Divisor == 0)
        return false;

    if (u32_Divisor > 1)
    {
        DWORD u32_Rest = 0;
        Divide32(&pk_Decimal->Hi32,  u32_Divisor, &u32_Rest); // Hi FIRST!
        Divide32(&pk_Decimal->Mid32, u32_Divisor, &u32_Rest);
        Divide32(&pk_Decimal->Lo32,  u32_Divisor, &u32_Rest);
    }
    return true;
}