【问题标题】:Euler 26 in HaskellHaskell 中的欧拉 26
【发布时间】:2019-02-05 07:09:41
【问题描述】:

我正在尝试解决来自 Haskell 的 Project Euler 的问题 #26,但遇到了一些问题。

我已经设法弄清楚倒数的循环周期只与它的素数除数有关,所以我想我只需要找出循环周期最长的素数的倒数。于是我用 Haskell 写了一个算法:

isPrime :: Int -> Bool
isPrime k
    | k <= 1    = error "Seriously?"
    | otherwise = null [ x | x <- [2..floor(sqrt(fromIntegral k))], k `mod` x == 0]

lp = [x | x <- [7..1000], isPrime x]

s = map (\n -> head [x | x <- [ceiling(logBase 10 (fromIntegral n))..], 10^x `mod` n == 1]) lp

main::IO()
main = print $ maximum s

但是,它无法产生答案。我尝试使用 lamda,它可以产生循环周期的数字,带有几个素数,我设法得到正确的数字数(我希望算法不会有问题)。我还检查了列表s 的输出,它产生了[6,2,6,16,18,45,23,15,3,5,63, 没有结束。我不知道为什么会这样,因为如果我手动将函数应用于每个素数,我可以获得正确的输出。

谁能告诉我我的代码有什么问题,或者我解决它的方法是错误的?谢谢。

【问题讨论】:

  • 该算法对我来说似乎还可以 - 不是特别有效,因此它可能会运行很长时间,但您打印出的值似乎是正确的(至少我检查过的值),并且s 不可能是无限的提升。如果到那时还没有人提出解释,我会尝试自己在 ghci 中测试它,但它必须等到我今晚在家。 [PS 为了速度,您可能只想找到所有小于 1000 的素数的列表,并将其硬编码为lp。]
  • @RobinZigmond 谢谢,我发现如果我设置函数f n = head [x | x &lt;- [ceiling(logBase 10 (fromIntegral n))..], 10^x `mod` n == 1],如果我直接输入像f 89 这样的素数,该函数会给出输出,但如果用@ 替换它就不能工作987654330@
  • @RobinZigmond 查看我对答案的编辑;并非所有结果都是正确的,这就是我意识到正在进行一些环绕算术的方式。它不是特别慢,需要几秒钟才能生成多达 1000 个的完整列表。
  • @MeowcolmLaw 它与89 一起使用,因为它把89 解释为polymorphic literal 类型为Num a =&gt; a,并默认为Integer
  • 我有时对 Haskell 打字感到沮丧。通常使用fromIntegral 可以快速修复,但这里不是。我通过消除使用n[ (n,x) | i &lt;- [n], x &lt;- [(ceiling.logBase 10 $ fromIntegral i)..], mod (10^x) i == 1 ] 来实现此功能,使用i 代替n。你可以使用let,但它会不那么紧凑。

标签: haskell


【解决方案1】:

Int 在这里不是一个好的选择,因为您使用10^x 操作的数字非常大。 IntBounded,所以绕过去了它的上限:

> maxBound :: Int
9223372036854775807

> (maxBound :: Int) + 1
-9223372036854775808

完全省略isPrime的签名,我们得到

> :t lp
lp :: Integral b => [b]

尝试

> map (\n -> (n, head [x | x <- [ceiling(logBase 10 (fromIntegral n))..],
                           10^x `mod` n == 1])) 
      (lp :: [Int])
[(7,6),(11,2),(13,6),(17,16),(19,18),(23,45),(29,23),(31,15),(37,3),(41,5),(43,63),
 (47,Interrupted.

我们发现您的计算卡在47 上。但是使用[Integer](或者什么都没有,所以它本身默认为Integer),我们成功地得到了完整的结果。你只是误解了它。重新阅读问题陈述,你就会明白了。

(另外,上面 sn-p 中 43 的答案是不正确的,而 7、11、13 的答案是正确的。对于更大的数字得到错误的结果是一个强烈的信号,表明我们有一些整数换行 -围绕正在发生的算术错误;这就是我发现它的方法。

【讨论】:

    猜你喜欢
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    相关资源
    最近更新 更多