【发布时间】:2014-08-07 10:53:44
【问题描述】:
我写了以下代码来检查一个数字是否是素数:
factorsOf :: Int -> [Int]
factorsOf n = [factor | factor <- [2..sqrtOfN], n `rem` factor == 0]
where sqrtOfN = round . sqrt $ fromIntegral $ n+1
isPrime :: Int -> Bool
isPrime n
| factorsOf n == [] = True
| otherwise = False
它有效,但我注意到一些奇怪的东西。如果我对一个大数(比如 100000001)运行 factorOf,则需要几秒钟来计算所有因素。如果我在同一个数字上运行 isPrime,如果它找到一个因素,它几乎会立即返回。 Haskell 是否真的跟踪函数将返回以支持(我假设)惰性求值的条件?如果是真的,那就太棒了。
【问题讨论】:
-
isPrime中的守卫只对factorsOf是否包含任何元素感兴趣。只要找到一个因素,就可以确定isPrime的结果。无需评估整个因素列表。 -
尝试将性能与较大的素数(例如 1000000007)作为输入进行比较。
-
@Xeo 这就是我的想法;这很酷。如果我想了解更多这方面的信息,是否有任何关于惰性评估的文章,或者守卫是一个特例?
-
@Niklas B. 我假设它需要的时间与 factorOf 通话时间一样长?
-
factorsOf 100000001是[17],它会立即计算。好吧,如果您在烤面包机上运行,那么也许,但在现代台式计算机上,没有 32 位数字对于这个计算来说是“大”的。想要大量因素吗?尝试factorsOf $ product [1..17],但将Int替换为Integer以获得任意精度的算术。对于非常非常的大型列表,请尝试product [1..20]。