使用UInt64替换BigInteger以进行素数分解算法,其中N <1。 2 ^ 63

时间:2015-08-13 11:18:52

标签: .net algorithm biginteger prime-factoring uint64

我使用Pollard's Rho and Brent's algorithms(参见:https://stackoverflow.com/a/31978350/44080

在VB.Net中使用BigInteger实现了Prime Factorization的良好解决方案

对于N< 2^63,我相信UInt64应该足够大,并且可能(很多?)更快。

但是,此行UInt64转换失败:

y = ((y^2) Mod n + c) Mod n 'fails when y^2 > UInt64.Max

将此行更改为

y = CULng((CDbl(y^2) Mod n + c) Mod n)

因类型转换处于循环中而导致性能下降。

请问我该如何解决这个问题?

如果我们能够解决上述问题,我仍然认为UInt64将会执行BigInteger。

修改

我刚刚发现:Dirichlet .NET Number Theory Library声称拥有Int128和Int256可以执行.Net BigInteger。

它甚至还有几种优化的Prime数分解算法。本可以节省我2天的研究和测试。

1 个答案:

答案 0 :(得分:1)

如何执行模块化乘法(计算平方)而不溢出:

只要模数至少比最大值小一位,解决方法就是将数字分成低位和高位的一半,然后执行算术零碎,有点像小学 - 学校乘法你在哪里乘以一个数字,然后移动总和并乘以十位,依此类推,除了“数字”是可以用整数数据类型表示的最大数的平方根的大小。

考虑使用8位算术计算56 * 37模100的示例,因此没有中间总数可以是256或更大。我们首先表示a = 56 = 3 * 16 + 8和b = 37 = 2 * 16 + 5,(注意16是256的平方根)所以:

a1 = 8
a2 = 3
b1 = 5
b2 = 2

然后四个中间产品的变化是:

p11 = 8 * 5 = 40
p12 = 8 * 2 = 16 > 32 > 64 > 128 (28) > 56
p21 = 3 * 5 = 15 > 30 > 60 > 120 (20) > 40
p22 = 3 * 2 = 6 > 12 > 24 > 48 > 96 > 192 (92) > 184 (84) > 168 (68) > 136 (36)

我们正在使用二进制算术,所以每个数字在移位时都会加倍,在我们去的时候取模100。两个低半数的乘积没有移位,低半数和高半数的乘积被移位4次(因为log 2 16 = 4),并且两个高的乘积 - 半数转移8次。然后对中间产物求和,每次中间和超过m时再次除去m:

s = 40 + 56 = 96
s = 96 + 40 = 136 (36)
s = 36 + 36 = 72

这是最终答案:56 * 37 = 2072,即72(mod 100)。

如果m在整数数据类型的最大值的一位内,则事情变得更加混乱;基本答案是分为三个部分,计算中间产品,并重新组合。

有关Scheme中的代码,请参阅my blog,以及使用稍微不同的算法的C中的贡献解决方案。