如何检查整数是否在普通Lisp中不是多维数据集?

时间:2019-04-23 09:22:20

标签: integer common-lisp

我需要定义一个lisp函数iscube,它将一个整数作为参数,如果n是一个立方体,则返回T,否则返回nil。

我只知道如何使整数成为一个多维数据集,但是如何确定一个整数就是一个多维数据集?

不允许我使用任何特殊的数学函数,例如log来解决此问题...

示例iscube(8)将返回true,与iscube(-8)将返回true。

3 个答案:

答案 0 :(得分:1)

您应该注意到,它似乎还不那么聪明,以至于无法完成您的作业。但是,由于我必须给我一些乐趣,所以可以从这里开始:

(defun is-cube-p (n)
   "Returns T if N is a cube number."
   (zerop (nth-value 1 (round (abs (expt n 1/3))))))

CL-USER> (is-cube-p -8)
T
CL-USER> (is-cube-p 8)
T
CL-USER> (is-cube-p 9)
NIL

我既不是数学家,也不是CL专业人士,因此无法保证这是解决问题的最佳方法。

答案 1 :(得分:0)

我将提供类似于Martin's的解决方案,它会比较慢。但这对于某些人来说可能更容易理解。

https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}?api-version=2018-06-01

这个想法是首先计算n的立方根,然后找到根的整数部分。我们将整数部分立方化回m并比较m和n。如果m == n,则n是一个立方体。

答案 2 :(得分:0)

此页面上的其他一些答案存在浮点精度问题,因此不正确;特别是,expt 可以返回浮点近似值。作为一个 commenter pointed out,这可能导致立方体的数字被报告为立方体。数字 9,261,000 是一个完全立方体(210 的立方体),但数字 9,261,101 不是一个完全立方体;然而这里的其他三个答案中有两个报告说 9,261,101 是一个完美的立方体。

一个good solution是找到n的立方根,将其转换为整数,然后将该整数的立方与n进行比较,避免精度问题。

>

另一种解决方案是对整数值使用二进制搜索。我在这里包含这个解决方案并不是因为它是最好的解决方案,而是因为记住二进制搜索等基本思想可以被广泛应用是很好的。在您不确定如何处理浮点精度问题的情况下,对整数进行二分搜索可能会得到正确的结果。

(defun cubep (n)
  (let ((n (abs n)))
    (flet ((midpoint (a b) (truncate (+ a b) 2))
           (closep (a b) (< (- b a) 2)))
      (labels ((bsearch (start end)
                 (let* ((mid (midpoint start end))
                        (mid-cubed (expt mid 3)))
                   (cond ((closep start end) nil)
                         ((< mid-cubed n)
                          (bsearch mid end))
                         ((> mid-cubed n)
                          (bsearch start mid))
                         (t t)))))
        (or (zerop n)  ; test ends of search range
            (= n 1)
            (bsearch 0 n))))))

这里,因为有立方根的非负数对应有立方根的负数,所以只考虑n的绝对值。搜索 0 到 n 之间的整数,直到找到 n 的立方根,或者直到搜索间隔太小而无法包含另一个整数。

CL-USER> (cubep 8)
T
CL-USER> (cubep -27)
T
CL-USER> (cubep 11)
NIL
CL-USER> (cubep 9261000)
T
CL-USER> (cubep 9261001)
NIL

当数字开始变大时,前面提到的浮点精度问题就会变得明显。这是一个比较两种实现结果的函数:

(defun compare (func1 func2 a b)
  (let ((failures (loop for n from a to b
                        unless (eql (funcall func1 n) (funcall func2 n))
                          collect n)))
    (if (null failures)
                     (format t "PASSED~%")
                     (format t "FAILURES: ~A~%" failures))))

这是将cubep与错误的cube-p进行比较的结果;由于浮点数处理不当,9,260,000 和 10,000,000 之间的 12 个数字被误报为完美立方体。这些是很大的输入数字,但它们并没有那么大。错误版本的 is-cube-p 结果相同:

CL-USER> (compare #'cubep #'cube-p 9260000 10000000)
FAILURES: (9260999 9261001 9393930 9393932 9528127 9528129 9663596 9663598
           9800343 9800345 9938374 9938376)