Lisp-素数
我正在努力学习lisp,我在素数方面有一些困难。我需要一个函数Lisp-素数,lisp,common-lisp,primes,primality-test,Lisp,Common Lisp,Primes,Primality Test,我正在努力学习lisp,我在素数方面有一些困难。我需要一个函数是prime,如果是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
是prime
,如果是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) )))))
但是我有两个参数,我不知道如何只用一个。另外,它根本不起作用。有人能帮我吗?谢谢 你已经走到一半了 以下是我的英文解释: 您已经在lisp中编写了一个函数is prime(顺便说一句,“yes或no”这样的函数在lisp中通常被命名为whatever-p),它告诉您n相对于d是否是prime 你需要做的是遍历所有小于n的d,如果它不是它们中任何一个的相对素数,则返回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。您在这方面有一些错误:
(defun is-prime (n d)
(if (= d 1)
(print "t")
(if (= (% n d) 0)
(print "nil")
首先,不要打印结果,只需返回即可。其次,没有%
函数,它是rem
真正的错误是如何进行递归调用。这里有一对额外的括号:
(is-prime (n (- d 1) )))))
; ^ ^
; this and this
在Lisp中,括号表示函数调用;但是您不打算用参数(-d1)
调用n
,它们都是is prime
的参数。所以我们只需要去掉那些额外的括号
(is-prime n (- d 1) ))))
那么它有什么作用呢?它倒计时:d
,(-d1)
<代码>1。当(=d1)
时,它返回t
。所以,有一种说法是
(defun is-prime (n &optional (d (- n 1)))
(or (= d 1)
(and (/= (rem n d) 0)
(is-prime n (- d 1)))))
但这不是最有效的方法,也不是最安全的方法
首先,最好是向上计数,而不是向下计数,因为任何随机数的因子都比大的要小得多。然后,它让我们优化我们停在哪里——停在
sqrt
更有效,同样正确。我从威尔·内斯的答案中得到启发,修改了函数。这是代码。Is检查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,因此如果这方面有问题,请告诉我。我知道您在这里做什么,但我试图使其递归。如何使其递归并只保留一个参数n?可能,但这不是尾部递归的候选者,因此没有很好的理由使其递归(Lisp不仅仅是递归函数…)。让我看看我能做些什么…这看起来很光滑。你能评论一下递归和参数传递吗?函数是否在每次传递递减的第二个参数时调用自身?@ArtforLife“函数是否在每次传递递减的第二个参数时调用自身?”是。不是所有的时间,只要它需要这样做——也就是说,如果
d
不是1
(当t
返回时),并且(rem n d)
不是0
(当NIL
返回时)。我明白了。使用参数1调用函数时,函数似乎会中断。它以零除法。@ArtforLife right.:)这就是我暗示的,用“不是……最安全的[调用此函数的方式]”:)知道了。那么一开始就应该进行一些检查了?此外,只需检查d=isqrt(n)
及以下项即可进行优化。最好从2向上计数到sqrt(n)(包括),而不是从(n-1)向下计数到2。而且,CommonLisp不喜欢递归;你的意图是一个循环,所以最好把它写成一个循环。使用循环
,或执行
,或程序
偶数。至于您的代码,您仍然没有处理(
的情况。