我正在努力学习口齿不清,而且我对素数有些困难。我需要一个函数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个参数,我不知道如何只使用一个。而且,它根本不起作用。谁能帮我这个?谢谢!
答案 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。