分数大

时间:2009-11-27 12:26:09

标签: c++ biginteger division

我需要一些可以处理大整数(128位)的除法算法。 我已经问过如何通过位移操作符来做到这一点。但是,我目前的实施似乎要求更好的方法

基本上,我将数字存储为格式为

的两个long long unsigned int

A * 2 ^ 64 + BB < 2 ^ 64

这个数字可以被24整除,我想把它除以24

我目前的做法是将其转换为

A * 2 ^ 64 + B     A             B
--------------  = ---- * 2^64 + ----
      24           24            24

           A               A mod 24                    B         B mod 24
= floor( ---- ) * 2^64 +  ---------- * 2^64 + floor( ---- ) +   ----------
           24               24.0                      24           24.0

然而,这是错误的。

(请注意,楼层为A / 24modA % 24。正常分区存储在long double中,整数存储在long long unsigned int中。

由于24在二进制中等于11000,因此第二个加数不应该在第四个加数的范围内改变,因为它向左移动了64位。

因此,如果A * 2 ^ 64 + B可以被24整除,而B不可以,则很容易显示它是错误的,因为它会返回一些非整数。

我的实施中出现了什么错误?

5 个答案:

答案 0 :(得分:13)

我能想到的最简单的方法是将128位数字视为四个32位数字:

A_B_C_D = A*2^96 + B*2^64 + C*2^32 + D

然后在24岁之前进行长时间划分:

E = A/24 (with remainder Q)
F = Q_B/24 (with remainder R)
G = R_C/24 (with remainder S)
H = S_D/24 (with remainder T)

其中X_Y表示X*2^32 + Y。 然后答案为E_F_G_H,其余为T。在任何时候你只需要划分64位数字,所以这应该仅适用于整数运算。

答案 1 :(得分:2)

这可能通过反向乘法来解决吗?首先要注意的是24 == 8 * 3所以

的结果
a / 24 == (a >> 3) / 3

x = (a >> 3)然后分割的结果为8 * (x / 3)。现在仍然可以找到x / 3的价值。

模块化算术表明存在n个数n * 3 == 1 (mod 2^128)。这给出了:

x / 3 = (x * n) / (n * 3) = x * n

仍然需要找到常数n。有关如何在wikipedia上执行此操作的说明。您还必须实现乘以128位数的功能。

希望这有帮助。

/A.B。

答案 2 :(得分:1)

你不应该将long double用于你的“正常分歧”,而应该使用整数。 long double没有足够的有效数字来得到正确的答案(无论如何,整个操作都要做到这一点,对吗?)。

答案 3 :(得分:1)

  

由于二进制24等于11000,所以第二个加数不应该在第四个加数范围内改变,因为它向左移64位。

你的公式是用实数写的。 (一个mod 24)/ 24可以有任意数量的小数(1/24例如0.041666666 ...)因此可以干扰分解中的第四个项,即使一次乘以2 ^ 64。

Y * 2 ^ 64不会干扰加法中较低权重二进制数的属性仅在Y为整数时有效。

答案 4 :(得分:1)

别。

去抓一个库来做这些事情 - 在调试奇怪的错误时,你会非常感谢你选择。

Snippets.org不久前在它的网站上有一个C / C ++ BigInt库,谷歌也发现了以下内容:http://mattmccutchen.net/bigint/