在32位整数数学中,add和multiply的基本数学运算隐式计算mod 2 ^ 32,这意味着你的结果将是加或乘的最低位。
如果要使用不同的模数计算结果,您当然可以使用不同语言的任意数量的BigInt类。并且对于值a,b,c< 2 ^ 32你可以用64位长的int来计算中间值,并使用内置的%运算符来减少到右边的答案
但是我被告知当C的形式为(2 ^ N)-1或(2 ^ N)+1时,有一些特殊的技巧可以有效地计算a * b mod C,它们不使用64比特数学或BigInt库是非常有效的,比任意模数评估更有效,并且还适当地计算如果包括中间乘法通常会溢出32位int的情况。
不幸的是,尽管听说这种特殊情况有快速评估方法,但实际上我还没有找到该方法的描述。 “那不是在Knuth吗?” “这不就是维基百科上的某个地方吗?”是我听到的咕。声。
显然,随机数生成器中的常用技术是a * b mod 2147483647的乘法,因为2147483647是等于2 ^ 31 -1的素数。
所以我会问专家。什么是这个聪明的特殊情况乘法与mod方法,我找不到任何讨论?
答案 0 :(得分:10)
我认为诀窍如下(我将在10号基地进行,因为它更容易,但原则应该成立)
假设您正在乘以a*b mod 10000-1
和
a = 1234 = 12 * 100 + 34
b = 5432 = 54 * 100 + 32
现在a*b = 12 * 54 * 10000 + 34 * 54 * 100 + 12 * 32 * 100 + 34 * 32
12 * 54 * 10000 = 648 * 10000
34 * 54 * 100 = 1836 * 100
12 * 32 * 100 = 384 * 100
34 * 32 = 1088
自x * 10000 ≡ x (mod 10000-1)
[1]以来,第一个和最后一个词变为648 + 1088。第二个和第三个术语是'技巧'进来的地方。注意:
1836 = 18 * 100 + 36
1836 * 100 ≡ 18 * 10000 + 3600 ≡ 3618 (mod 10000-1).
这基本上是循环转变。给出648 + 3618 + 8403 + 1088的结果。并且还要注意,在所有情况下,乘以的数字都是&lt; 10000(因为&lt; 100和b <100),所以如果您只能将多个2位数字组合在一起,并且添加它们,则可以计算出来。
在二进制文件中,它会以类似的方式运作。
以a和b开头,均为32位。假设你想将它们乘以mod 2 ^ 31 - 1,但你只有一个16位乘法器(给出32位)。算法将是这样的:
a = 0x12345678
b = 0xfedbca98
accumulator = 0
for (x = 0; x < 32; x += 16)
for (y = 0; y < 32; y += 16)
// do the multiplication, 16-bit * 16-bit = 32-bit
temp = ((a >> x) & 0xFFFF) * ((b >> y) & 0xFFFF)
// add the bits to the accumulator, shifting over the right amount
total_bits_shifted = x + y
for (bits = 0; bits < total_bits_shifted + 32; bits += 31)
accumulator += (temp >> (bits - total_bits_shifted)) & 0x7FFFFFFF
// do modulus if it overflows
if (accumulator > 0x7FFFFFFFF)
accumulator = (accumulator >> 31) + (accumulator & 0x7FFFFFFF);
已经很晚了,所以累加器部分可能无法正常工作。我认为原则上它是正确的。有人可以随意编辑它以使其正确。
展开,这也是非常快的,这是PRNG使用的,我猜。
[1]: x*10000 ≡ x*(9999+1) ≡ 9999*x + x ≡ x (mod 9999)
答案 1 :(得分:3)
假设您可以将* b计算为p*2^N+q
。这可能需要64位计算,或者您可以将a和b拆分为16位部分并以32位计算。
a*b mod 2^N-1 = p+q mod 2^N-1
以后2^N mod 2^N-1 = 1
。
a*b mod 2^N+1 = -p+q mod 2^N+1
以及2^N mod 2^N+1 = -1
。
在这两种情况下,2^N-1
或2^N+1
都没有划分。
答案 2 :(得分:2)
快速搜索了这个:http://home.pipeline.com/~hbaker1/AB-mod-N.pdf。不幸的是,对于我来说,仅仅用简化的公式来写出足够的意义已经太晚了,但它可能在那篇论文中。
答案 3 :(得分:1)
您可以使用Montgomery reduction(还有其他descriptions)来降低模块化乘法计算的成本,而不是在每个步骤中进行模块缩减。但是,这仍然不使用N的属性加/减2的幂。
答案 4 :(得分:1)
您正在寻找的身份是x mod N = (x mod 2^q)- c*floor(x/2^q)
,假设N = 2^q + c
且c是任何整数(但通常为±1)。
你可能想阅读第9.2.3节:“特殊形式的模数”在“Prime Numbers:A Computational Perspective”中由Richard Crandall和Carl Pomerance阅读。除了理论之外,它还包含用于实现上述关系的算法的伪代码。
答案 5 :(得分:0)
我在这个主题上找到了rather extensive page,不仅讨论了算法,还讨论了问题和解决方案的具体历史以及人们使用解决方案的方式。