我需要一些可以处理大整数(128位)的除法算法。 我已经问过如何通过位移操作符来做到这一点。但是,我目前的实施似乎要求更好的方法
基本上,我将数字存储为格式为
的两个long long unsigned int
A * 2 ^ 64 + B
与B < 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 / 24
,mod
为A % 24
。正常分区存储在long double
中,整数存储在long long unsigned int
中。
由于24
在二进制中等于11000
,因此第二个加数不应该在第四个加数的范围内改变,因为它向左移动了64位。
因此,如果A * 2 ^ 64 + B
可以被24整除,而B不可以,则很容易显示它是错误的,因为它会返回一些非整数。
我的实施中出现了什么错误?
答案 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/