Math 为c=2^N+快速计算(a*b)mod c-1.

Math 为c=2^N+快速计算(a*b)mod c-1.,math,integer,modulo,prng,knuth,Math,Integer,Modulo,Prng,Knuth,在32位整数数学中,加法和乘法的基本数学运算以mod 2^32隐式计算,这意味着您的结果将是加法或乘法的最低阶位 如果您想用不同的模计算结果,您当然可以使用不同语言中任意数量的BigInt类。对于值a、b、c(位-总位移位))&0x7FFFFFFF //如果溢出,请不要打开 if(累加器>0x7FFFFFF) 累加器=(累加器>>31)+(累加器&0x7FFFFFFF); 时间不早了,所以蓄能器部分可能无法工作。但我认为原则上这是正确的。有人可以随意编辑,使其正确 展开,这是相当快,以及,这是

在32位整数数学中,加法和乘法的基本数学运算以mod 2^32隐式计算,这意味着您的结果将是加法或乘法的最低阶位

如果您想用不同的模计算结果,您当然可以使用不同语言中任意数量的BigInt类。对于值a、b、c<2^32,您可以计算64位长整数中的中间值,并使用内置的%运算符将其缩减为正确的answe

但有人告诉我,当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的特殊情况乘法方法是什么,我找不到任何讨论?

快速搜索出现了以下内容:。不幸的是,对于我来说,用简化的公式来解释这一点已经太晚了,但它可能就在那篇论文的某个地方。

假设你可以将a*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

而不是在每一步进行模约化,您可以使用(还有其他)来降低模乘计算的成本。不过,这仍然没有使用N是2的正/负幂的性质

我认为诀窍如下(我将在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(型号10000-1)。
这本质上是一个循环变化。给出648+3618+8403+1088的结果。还要注意的是,在所有情况下,相乘的数字都小于10000(因为a<100,b<100),所以如果您只能将两位数相加,则这是可以计算的

在二进制中,它的结果是类似的

从a和b开始,都是32位。假设你想将它们乘以mod 2^31-1,但是你只有一个16位的乘法器(给出32位)。算法如下所示:

a=0x12345678
b=0xfedbca98
累加器=0
对于(x=0;x<32;x+=16)
对于(y=0;y<32;y+=16)
//进行乘法运算,16位*16位=32位
温度=((a>>x)和0xFFFF)*((b>>y)和0xFFFF)
//将位添加到累加器中,切换到正确的量
总位移位=x+y
用于(位=0;位<总位移位+32;位+=31)
累加器+=(温度>>(位-总位移位))&0x7FFFFFFF
//如果溢出,请不要打开
if(累加器>0x7FFFFFF)
累加器=(累加器>>31)+(累加器&0x7FFFFFFF);
时间不早了,所以蓄能器部分可能无法工作。但我认为原则上这是正确的。有人可以随意编辑,使其正确

展开,这是相当快,以及,这是什么PRNG使用,我猜

[1]: x*10000 ≡ x*(9999+1) ≡ 9999*x + x ≡ x (mod 9999)
[1] :x*10000≡ x*(9999+1)≡ 9999*x+x≡ x(mod 9999)如果
N=2^q+c
且c为任意整数(但通常为±1),则您要查找的标识是
x mod N=(x mod 2^q)-c*floor(x/2^q)


您可能想阅读Richard Crandall和Carl Pomerance的“质数:计算视角”中的第9.2.3节:“特殊形式的模”。除了理论之外,它还包含实现上述关系的算法的伪代码。

我在这个主题上找到了一个答案,不仅讨论了算法,甚至还讨论了问题和解决方案的具体历史以及人们使用解决方案的方式

本文使用浮点算法而不是N的性质来提高计算效率。我自己对浮点计算有点紧张,但没有比这更深入的检查。。。这可能足够好了。有趣的论文,值得一读!这是一种适用于任意模量值的更通用的方法。不幸的是,作为计算的一部分,它将值转换为64位双倍。一般来说,这可能是一个非常有效的计算,但是对于特殊的c=2^N+-1情况,有一些更快的方法+无论如何,我要投上一票,因为这是一个很好的链接!我仍然不理解这背后的数学原理,这就是为什么我在大学里放弃了数学辅修课程……嗯,这有点像是用9(10-1)除以余数。你只要把数字加起来就行了。现在,在本例中,不是基数10或基数2,而是“基数”2^NAre