如何在Clojure中检查一个数是否为斐波那契数?

如何在Clojure中检查一个数是否为斐波那契数?,clojure,Clojure,输入:一个正整数 输出:基于测试的真/假 以下是我的尝试: (defn is-a-fib? [x] "Check whether x is a fibonacci number. Algorithm: test whether 5x^2+4 or 5x^2-4 is a perfect square." (let [a (+' (*' (Math/pow x 2) 5) 4) ; 5x^2+4 b (-' (*' (Math

输入:一个正整数

输出:基于测试的真/假

以下是我的尝试:

(defn is-a-fib? [x]
  "Check whether x is a fibonacci number.
   Algorithm: test whether 5x^2+4 or 5x^2-4 is a perfect square."
  (let [a (+' (*' (Math/pow x 2) 5) 4)                      ; 5x^2+4
        b (-' (*' (Math/pow x 2) 5) 4)                      ; 5x^2-4
        sqrt-a (Math/sqrt a)
        sqrt-b (Math/sqrt b)]
    (or (== (*' sqrt-a sqrt-a)
            (*' (Math/floor sqrt-a) (Math/floor sqrt-a)))  ; Test whether n is a perfect square
        (== (*' sqrt-b sqrt-b)
            (*' (Math/floor sqrt-b) (Math/floor sqrt-b))))))
问题是:这段代码不适用于大量用户。我认为这可能会导致堆栈溢出。
有更好的方法吗?

在精度范围有限的双精度上,对双精度进行运算的
运算将产生舍入误差

如果你从这个角度来看,事情可能仅仅因为四舍五入而出轨,但当你用尽了精度(15–17位小数)时,它们真的会出错

第一个第n个Fibonnacci,其中该算法给出了后续整数的假阳性,是与n=74相关的16位整数

编辑:添加任意精度的解决方案,以避免双重
s:

主要的困难是缺少整数平方根算法

可翻译为Clojure:

(defn integer-sqrt [n]
  (let [n (biginteger n)]
    (loop [a BigInteger/ONE
           b (-> n (.shiftRight 5) (.add (biginteger 8)))]
      (if (>= (.compareTo b a) 0)
        (let [mid (-> a (.add b) (.shiftRight 1))]
          (if (pos? (-> mid (.multiply mid) (.compareTo n)))
            (recur a (.subtract mid BigInteger/ONE))
            (recur (.add mid BigInteger/ONE) b)))
        (dec a)))))
有了它,您可以定义任意精度的完美平方测试:

(defn perfect-square? [n]
  (let [x (integer-sqrt n)]
    (= (*' x x) n)))
并更新您的实现以使用它:

(defn is-a-fib? [x]
  "Check whether x is a fibonacci number.
   Algorithm: test whether 5x^2+4 or 5x^2-4 is a perfect square."
  (let [a (+' (*' (*' x x) 5) 4)                            ; 5x^2+4
        b (-' (*' (*' x x) 5) 4)]                           ; 5x^2-4
    (or (perfect-square? a)
        (perfect-square? b))))

是什么让您相信它会导致堆栈溢出?你知道什么是堆栈溢出吗?(看来你不知道)。不,这不是问题所在。这个问题更可能存在于浮点运算中。谢谢!是的,你的解释很清楚。那么,如何使代码适用于大数?@Nick我预料到了你接下来的问题,并编辑了答案,以提供一个示例,说明如何修改内容以使用任意精度运算。在我看来,
数学/sqrt
是需要克服的主要障碍。谢谢!整数sqrt是程序中最难的部分。您将完美正方形作为一个单独的函数,使代码易于阅读。好学!
(defn is-a-fib? [x]
  "Check whether x is a fibonacci number.
   Algorithm: test whether 5x^2+4 or 5x^2-4 is a perfect square."
  (let [a (+' (*' (*' x x) 5) 4)                            ; 5x^2+4
        b (-' (*' (*' x x) 5) 4)]                           ; 5x^2-4
    (or (perfect-square? a)
        (perfect-square? b))))