Lisp - 素数

时间:2013-12-15 22:16:13

标签: lisp common-lisp primes primality-test

我正在努力学习口齿不清,而且我对素数有些困难。我需要一个函数is-prime,如果它是素数,我必须返回t,如果不是,我必须返回nil

(prime 41) => t

(prime 35) => nil

到目前为止,我已经:

(defun is-prime (n d) 
  (if (= d 1) 
      (print "t") 
      (if (= (% n d) 0) 
          (print "nil") 
          (is-prime (n (- d 1) )))))

但我有2个参数,我不知道如何只使用一个。而且,它根本不起作用。谁能帮我这个?谢谢!

3 个答案:

答案 0 :(得分:5)

你在那里几乎没有失误:

(defun is-prime (n d) 
  (if (= d 1) 
      (print "t") 
      (if (= (% n d) 0) 
          (print "nil") 

首先,不要print你的结果,只需归还它们。其次,没有%函数,它是rem

真正的错误是你如何进行递归调用。你有一个额外的括号:

          (is-prime (n (- d 1) )))))
          ;         ^          ^

在Lisp中,括号表示函数调用;但您不打算使用参数n来调用(- d 1),它们都是is-prime的参数。所以我们只需将其改为

          (is-prime  n (- d 1)  ))))

那它是做什么用的?它倒计时:d(- d 1) ... 1。当(= d 1)时,它会返回t。所以,调用它的一种方法是

(defun is-prime (n &optional (d (- n 1))) 
  (or (= d 1)
      (and (/= (rem n d) 0)
           (is-prime  n (- d 1)))))

但它不是最有效的方式,也不是最安全的方式。计算起来要好得多,而不是一件事,因为任何数字都可能比较大的因素更有可能。然后,它可以让我们优化停止的位置。

答案 1 :(得分:1)

我把Will Ness的答案作为灵感并修改了这个功能。这是代码。检查1是否作为参数传递,并确保在这种情况下输出nil

(defun is-prime (n &optional (d (- n 1))) 
  (if (/= n 1) (or (= d 1)
      (and (/= (rem n d) 0)
           (is-prime  n (- d 1)))) ()))

我还在学习Common Lisp,所以如果有问题,请告诉我。

答案 2 :(得分:0)

嗯,你已经到了一半。

以下是我的英文解释:

你已经在lisp中写了一个函数is-prime(btw,“是或否”函数,通常在lisp中命名为whatever -p),它告诉你n是否相对到d

你需要做的是仔细阅读所有小于n的内容,如果 不是相对于其中任何一个,请返回 nil ,但是如果在该循环之后你没有返回 nil ,然后返回 t 。你的朋友在这里是函数“mod”,它告诉你当第一个参数除以第二个参数时是否有余数。

类似的东西:

(defun primep (n)
 (cond
  ((= 1    n)          nil)
   (t
   (loop
     :with root     = (isqrt n)
     :with divisors = (loop :for i :from 3 :to root :by 2 :collect i)
     :for d = (pop divisors)
     :if (zerop (mod n d))
     :do (return nil)
     :else :do (setf divisors (delete-if (lambda (x) (zerop (mod x d))) divisors))
     :while divisors
     :finally (return t)))))

另外,不要打印nil,只返回nil。