我有一个128位数字存储为2个64位数字(“Hi”和“Lo”)。我只需要将它除以32位数。我怎么能这样做,使用CPU的本机64位操作?
(请注意,我不需要任意精度库。只需要知道如何使用本机操作进行简单划分。谢谢。)
答案 0 :(得分:3)
如果使用您的架构可以处理的最大可能本机表示(64位)来存储值(128位),则在处理除法的中间结果时会遇到问题(如您已经找到的那样:)。 / p>
但是你总是可以使用SMALLER表示法。四位数的32位怎么样?这样,您可以使用本机64位操作而不会出现溢出问题。
可以找到一个简单的实现(在Delphi中)here。
答案 1 :(得分:2)
一些c代码here。
答案 2 :(得分: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;
}
答案 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;
}