3

我正在尝试将此算法移植到clojure。

我的代码是

(defn calc-iterations [x y] 
  (let [c (struct complex x y)]
    (loop [z (struct complex 0 0) 
           iterations 0]
      (if (and (< 2.0 (abs z))
               (> max-iterations iterations))
        iterations
        (recur (add c (multiply z z)) (inc iterations))))))

乘法、加法和 abs 函数正在正常工作。我用计算器测试过它们。但是对于以下值:

(calc-iterations 0.60703135 -0.33984375) ; should give me 2, instead I get 4
(calc-iterations -1.8421874 0.3515625 )  ; should give me 1, instead I get 3

我正在使用我在网上找到的另一个 java 小程序检查正确的迭代次数。它似乎正在工作,因为它产生了正确的输出。其迭代函数为

protected int calcIterations( float x, float y ) {
    int iterations = 0;

    float xn = x, yn = y;

    while ( iterations < MAX_ITERATIONS ) {
        float xn1 = xn*xn - yn*yn;
        float yn1 = 2*xn*yn;

        xn = xn1 + x;
        yn = yn1 + y;

        float magsq = xn*xn + yn*yn;

        if ( magsq > 4 )
            break;

        iterations++;
    }

    System.out.println( x + " " + y + " " + iterations );
    return iterations;
}

谁能发现我的错误?

4

1 回答 1

8

我发现了两个不同之处。

  1. Java 实现从 z = (x, y) 开始,而不是你的从 (0, 0) 开始。由于您的递归公式是 z = z^2 + c, (0, 0)^2 + (x, y) = (x, y) 所以从 (x, y) 开始与第一次迭代相同。因此,因此迭代次数将比您的少一。
  2. Java 实现检查结果 z 是否在距离原点 2 个单位范围内后增加迭代次数,否则不会增加它,而您的每次都增加迭代次数。因此,迭代次数也会比你的少一。

所以这可能解释了你的结果的差异。

我认为您的实现更正确,因为它区分了 |z| 的情况。> 2 在一次迭代后(即其中 |(x,y)| > 2),并且其中 |z| > 2 在两次迭代之后(即其中 |(x^2-y^2+x, 2xy+y)| > 2),而 Java 实现将执行其第一次迭代,给出 (x^2-y^2+x , 2xy+y),并在增加迭代次数之前退出,因此不区分这种情况。

于 2009-07-11T00:30:44.227 回答