Mod 哈斯克尔家庭作业
我的作业是提供一个计算 'x^y mod n' 的函数 - 对于任何 n < (sqrt maxint32)
所以我开始这样做:
modPow :: Int -> Int -> Int -> Int
modPow x y n = (x `mod` n) ^ (y `mod` n) `mod` n
对于任意数量的n,这似乎都可以正常工作,尽管我的下一个家庭作业问题涉及使用x^n mod n = x(Camichael数字)并且我永远无法让modPow工作。
因此,我使用伪代码进行模幂运算,制作了另一个 modPow,-来自维基百科:
modPow2 :: Int -> Int -> Int -> Int
modPow2 x y n
= loopmod 1 1
where
loopmod count total = if count > y
then total
else loopmod (count+1) ((total*x) `mod` n)
现在可以正确地为我的下一个问题生成正确的答案,(x^n mod n = x) -用于检查 Camichael 数字。
尽管如此,modPow2 不适用于大量“y”(堆栈溢出!!)
我如何调整 modPow2,以便在 y > 的情况下不再出现堆栈溢出? 10,000(但仍小于 maxint 32 的 sqrt - 约为 46,000)
或者是否对我的原始 modPow 进行了修复,以便它可以与 x^n mod n = x 一起使用? (我总是做 560 561 561 作为输入,它给我返回 1 而不是 560 (561 是一个卡迈克尔数字,所以应该给我返回 560)
非常感谢。
My homework was to provide a function that computes 'x^y mod n' -for any n < (sqrt maxint32)
So I started by writing doing this:
modPow :: Int -> Int -> Int -> Int
modPow x y n = (x `mod` n) ^ (y `mod` n) `mod` n
Which seemed to work fine, for any number of n, although my next homework question involved using x^n mod n = x (Camichael numbers) and I could never get modPow to work.
So I made another modPow using pseudocode for mod exponentiation, -from wikipedia:
modPow2 :: Int -> Int -> Int -> Int
modPow2 x y n
= loopmod 1 1
where
loopmod count total = if count > y
then total
else loopmod (count+1) ((total*x) `mod` n)
Which now correctly produces the right answer for my next question, (x^n mod n = x) -for checking for Camichael numbers.
ALTHOUGH, modPow2 does not work for big numbers of 'y' (STACK-OVERFLOW!!)
How could I adjust modPow2 so it no longer gets a stackoverflow in the cases where y > 10,000 (but still less than sqrt of maxint 32 -which is around 46,000)
Or is there a fix on my original modPow so it works with x^n mod n = x? (I always do 560 561 561 as inputs and it gives me back 1 not 560 (561 is a carmichael number so should give 560 back)
Thanks alot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的
modPow
公式是错误的,您不能只使用 y mod n 作为指数,这会导致错误的结果。例如:要获得更好的
modPow
函数,您可以使用x2n+1 = x2n ⋅ x
和x2n = xn ⋅ xn
而对于乘法你实际上< em>可以简单地使用因子的mod
。Your formula for
modPow
is wrong, you can't just use y mod n as the exponent, it will lead to wrong results. For example:For a better
modPow
function you could use thatx2n+1 = x2n ⋅ x
andx2n = xn ⋅ xn
and that for multiplication you actually can simply use themod
of the factors.您从哪里获得
modPow
的公式?(x ^ y) `mod` n
=((x `mod` n) ^ (y `mod` φ n)) `mod` n
其中φ
是欧拉 totient 函数。Where did you get your formula for
modPow
from?(x ^ y) `mod` n
=((x `mod` n) ^ (y `mod` φ n)) `mod` n
whereφ
is Euler's totient function.这可能是因为参数
total
是延迟计算的。如果您使用 GHC,您可以通过放置 ! 来使
loopmod
在total
中严格。在参数前面,即另一种方法是强制计算总计,如下所示: 将最后一行替换为
这不会改变语义(因为
0*x
无论如何都是 0,因此提醒必须为 0也)并且它强制拥抱在每次递归中评估总数。This is probably because the argument
total
is computed lazily.If you use GHC, you can make
loopmod
strict intotal
by placing a ! in frontof the argument, i.e.Another way would be to force evaluation of total like so: Replace the last line with
This does not change semantics (because
0*x
is 0 anyway, so the reminder must be 0 also) and it forces hugs to evaluate total in every recursion.如果您正在寻找实现( a^d mod n )那么
If you are looking for implementation ( a^d mod n ) then