Clojure/Java Mandelbrot分形绘图

Ham*_*aya 3 lisp java clojure mandelbrot

我试图将此算法移植到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))))))
Run Code Online (Sandbox Code Playgroud)

乘法,加法和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
Run Code Online (Sandbox Code Playgroud)

我正在使用我在网上找到的另一个java applet检查正确的迭代次数.它似乎工作,因为它产生正确的输出.它的迭代功能是

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;
}
Run Code Online (Sandbox Code Playgroud)

谁能发现我的错误?

jam*_*les 8

我发现了两个不同之处.

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

因此,这可能会导致结果的差异.

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