Mod 哈斯克尔家庭作业

发布于 2024-12-09 14:00:24 字数 931 浏览 0 评论 0原文

我的作业是提供一个计算 '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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

瑕疵 2024-12-16 14:00:24

您的 modPow 公式是错误的,您不能只使用 y mod n 作为指数,这会导致错误的结果。例如:

Prelude> 2^10
1024
Prelude> 2^10 `mod` 10
4
Prelude> 2^(10 `mod` 10) `mod` 10
1

要获得更好的 modPow 函数,您可以使用 x2n+1 = x2n ⋅ xx2n = 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:

Prelude> 2^10
1024
Prelude> 2^10 `mod` 10
4
Prelude> 2^(10 `mod` 10) `mod` 10
1

For a better modPow function you could use that x2n+1 = x2n ⋅ x and x2n = xn ⋅ xn and that for multiplication you actually can simply use the mod of the factors.

野心澎湃 2024-12-16 14:00:24

您从哪里获得 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.

山人契 2024-12-16 14:00:24

这可能是因为参数 total 是延迟计算的。

如果您使用 GHC,您可以通过放置 ! 来使 loopmodtotal 中严格。在参数前面,即

loopmod count !total = ...

另一种方法是强制计算总计,如下所示: 将最后一行替换为

else if total == 0 then 0 else loopmod (count+1) ((total*x) `mod` n)

这不会改变语义(因为 0*x 无论如何都是 0,因此提醒必须为 0也)并且它强制拥抱在每次递归中评估总数。

This is probably because the argument total is computed lazily.

If you use GHC, you can make loopmod strict in total by placing a ! in frontof the argument, i.e.

loopmod count !total = ...

Another way would be to force evaluation of total like so: Replace the last line with

else if total == 0 then 0 else loopmod (count+1) ((total*x) `mod` n)

This does not change semantics (because 0*xis 0 anyway, so the reminder must be 0 also) and it forces hugs to evaluate total in every recursion.

浅黛梨妆こ 2024-12-16 14:00:24

如果您正在寻找实现( a^d mod n )那么

powM::Integer->Integer->Integer->Integer
powM a d n
   | d == 0 = 1
   | d == 1 = mod a n
   | otherwise = mod q n  where
       p = powM  ( mod ( a^2 ) n ) ( shiftR d 1 ) n
       q = if (.&.) d 1 == 1 then mod ( a * p ) n else p

If you are looking for implementation ( a^d mod n ) then

powM::Integer->Integer->Integer->Integer
powM a d n
   | d == 0 = 1
   | d == 1 = mod a n
   | otherwise = mod q n  where
       p = powM  ( mod ( a^2 ) n ) ( shiftR d 1 ) n
       q = if (.&.) d 1 == 1 then mod ( a * p ) n else p
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文