haskell 基础题解(03)

素数问题

【题目】 2,3,5,7,11 … 是前几个素数,求 1000 以内一共有多少个素数。
最容易想到的解法,当然是先造一个函数,能判断一个数是不是素数。
从2开始的小于 n的数字,如果能除尽 n,则n不是素数。

is_su :: Int -> Bool
is_su n = [ 1 | x <- [2..(n-1)], n `mod` x == 0 ] == []

su_shu = filter is_su [2..]
r = length $ takeWhile (<1000) su_shu

main = print r

haskell 的这种实现在简洁的同时,保持了很高的弹性。
将来题目的形式上的变化,很容易应对。这是纯函数思维一个附带的好处。
注意,[2…] 是一个无限的序列,因而su_shu 也是一个无限序列(这里受到了Int 签名的限制)

惰性的好处也显现出来。is_su 不会对所有可能的数去试除。因为它的惰性,只要有一个数字除开了, == [] 就不成立了,因而试除的工作也就不会继续下去了。

这种一旦出现 xxx情况就中止的模式也可以用 any 或 all 来更明确地表达出来:

is_su n = all (\x -> n `mod` x /= 0) [2..(n-1)]

这个表达式,简直就是素数的定义本身,你看,它读作:
素数就是:从2开始的,所有比它小的整数,都除不开它。

这种求素数的办法效率不高。有一种筛法目前仍然是比较高效的方式。
其思想是从2开始,把所有2的倍数全删掉。然后剩下的数字从3开始,再删去3的倍数…
最后剩下的就是素数了。

haskell 主页上引以傲的一段代码,正是用此法产生了一个无限的素数序列。

su_shu = f [2..] where 
    f (p:xs) =  p : f [x | x <- xs, x `mod` p /= 0]
num = length $ takeWhile (<1000) su_shu
main = print num

这段代码以如此简练的逻辑实现了一个无限的素数列,多少让人惊讶!当然,实际上求很大的素数时效率仍有问题。但你用 c 写个程序,来第10000个素数试试,就知道haskell的优美了。
现在,在 haskell 中,你只需要写: su_shu !! 10000
当然,如果你是笔记本上运行,要耐心等一会儿的。考虑到敲的这么几个码,你就知足吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值