从Haskell到功能的奇怪输出

时间:2012-03-25 21:51:39

标签: haskell

我正在写一些代码来帮助我学习一些数学知识。我正在尝试实施Miller测试,而不是Miller-Rabin,我需要列出一堆指数。这是迄今为止的代码。由于某种原因,它会将最后一次结果插入两次,我不知道为什么。我不能理解until函数是如何工作的。

import Math.NumberTheory.Powers

divides::Integer->Integer->Bool
divides x y = y `mod` x == 0

factorcarmichael::Integer->(Integer,Integer)
factorcarmichael n = until (\(_, s) -> not $ divides 2 s)
                           (\(r, s) -> (r+1, div s 2))
                           (0, n-1)

second::((Integer,Integer),[Integer])->[Integer]
second (x,xs) = xs

millerlist::Integer->Integer->[Integer]
millerlist a n =  second $ until (\((r,s), xs) -> r<0)
                                 (\((r,s), xs) -> ((r-1,s), (powerMod a ((2^r)*s) n):xs))
                                 (factoredcarmichael, [])
    where 
        factoredcarmichael = factorcarmichael n 

此外,millerlist功能有点笨拙。如果有人可以提出替代方案,那就太好了。

我得到的输出

millerlist 8888 9746347772161

重复最后一个元素两次。

1 个答案:

答案 0 :(得分:1)

那是因为

7974284540860^2 ≡ 7974284540860 (mod 9746347772161)

所以号码在列表中出现两次。但我相信,你的名单太长了。我认为您只希望a^(2^k*s) n模拟余下的0 <= k < r {/ 1}}。

至于替代方案,您有没有使用Math.NumberTheory.Primes.isStrongFermatPP的特殊原因?如果你只对结果感兴趣,那就不那么重要了。

如果要生成列表,那么

millerlist a n = go r u
  where
    (r,s) = factorcarmichael n
    u = powerMod a s n
    go 0 m = []
    go k m = m : go (k-1) ((m*m) `mod` n)

millerlist a n = take (fromInteger r) $ iterate (\m -> (m*m) `mod` n) u
  where
    (r,s) = factorcarmichael n
    u = powerMod a s n