我得到了圈而不是mandelbrot

时间:2016-06-06 09:02:09

标签: javascript math mandelbrot

enter image description here

我试图密切关注公式,但不知怎的,我得到的只是一个圆圈。这是在mandelbrot设置的坐标,我明白了很多。

for(x=-50;x<50;x++){
  for(y=-50;y<50;y++){

    // Canvas pixel coordinates to -2,2
    var x2 = x * 0.04;
    var y2 = y * 0.04;

    var i = 0;
    var z = 0;
    var c = Math.sqrt( x2*x2 + y2*y2 );

    while(true) {

      if( i > 20 || z > 4.0 ) {
        break;
      }

      z = z*z + c;

      i = i + 1;
    }
  }
}

的jsfiddle: https://jsfiddle.net/d4fj1n63/

2 个答案:

答案 0 :(得分:4)

您需要执行复杂的算术运算。

var x3 = 0, y3 = 0, k = 0;
while (x3*x3 + y3*y3 < 16 && k++ < 20) {
   var tmp = x3*x3 - y3*y3 + x2;
   y3 = 2*x3*y3 + y2;
   x3 = tmp;
}

公式为 z k +1 = z k 2 + c z 0 = 0或等效 z 1 = c
其中 c 是当前位置,即 c = x2 + i y2
我有 z = x3 + i y3所以 z 2 =( x3 + i y3 2 = x3 2 +2⋅ i x3y3 + i 2 y3 2
使用 i 2 = -1,这简化为 z 2 =(x3 2 - y3 2 )+ i ⋅(2⋅x3y3)并向我添加{ {1}}即cx2

请参阅https://jsfiddle.net/d5avqq5w/了解即时演示。

原始代码在y2步骤中丢弃了角度信息,因为在该点之后未使用z = Math.sqrt( x2*x2 + y2*y2 )x2。因此,得到的颜色 与角度无关,即由同心圆组成。

The page you gave as a reference处理复数的绝对值。但Mandelbrot公式的迭代步骤应该按原样对复数进行操作,而不是复数的任何绝对值,因此遵循该公式是不合适的。

有一个绝对值的有效应用,即在决定是否终止循环时(即检测分歧)。 The other page you referenced只写了

  

z n 的模数(长度)超过给定值。

没有明确给出阈值。我使用了阈值4,但我通过测试 z 长度的平方是否超过16来避免平方根。那就是y2 in我的代码来自。更常见的是使用2作为阈值(即4为平方测试),但我觉得使用4将更接近你所拥有的代码,即更适合强调比较绝对值和比较其平方之间的区别。使用4代替2可能会导致我们稍后检测到偏差,导致循环退出时计数器变量的值略高。

请注意,Wikipedia也有一些伪代码,您可能将其用作起点,并解释代码中的实值算法如何与本文其余部分中的复值算法相关联

答案 1 :(得分:2)

你犯了一个数学错误.C,Z是复数,但你把它们视为真实的。

我对您的代码进行了最小程度的更正,因此它按预期工作。

var canvas = $('canvas');
var ctx = canvas[0].getContext('2d');

for(x=-50;x<50;x++){
    for(y=-50;y<50;y++){

    var x2 = x * 0.04;
    var y2 = y * 0.04;

    var i = 0;
    var z = 0;
    //c - complex number. so c = x2+i*y2, where i^2 =-1 
    //var c = Math.sqrt( x2*x2 + y2*y2 );
    var xi= x2;
    var yi=y2;

    while(true) {


      if( i > 50 || xi*xi+yi*yi > 4.0 ) {
        break;
      }

      // z - complex number, so on every step we should calculate real and imaginary parts
      //z^2 = (x^2-y^2)+i*(2*x*y), i^2 =-1
      var tmp = xi*xi - yi*yi+x2;
      yi = 2*xi*yi+y2;
      xi = tmp;
      i = i + 1;
    }

    var color = parseInt(15/21*i).toString(16);
    ctx.fillStyle = '#'+color+color+color;

    ctx.fillRect((x+50)*2,(y+50)*2,2,2);
  }
}

jsFiddle enter image description here