多年来,The Mandelbrot set 一直是我的最爱。几年前,我已经在Pascal上成功创建了它,最近又在TI-83图形计算器上成功创建了它(Java使其更快地成熟了)。

由于涉及到复数,因此我从使用extends RecursiveActionBufferedImageForkJoinPool文本中获取了一个版本(不了解这些概念和总体实现),并使用了我几个月前开发的例程进行了修改(进行点绘图的代码,使它看起来更像是复数。

原版的:

public class MandelbrotTask extends RecursiveAction  {


...

public void render() {


...

for (int x = xStart; x <= xEnd; x++) {
  for (int y = yStart; y <= yEnd; y++) {
    double r = x * zoomFactor / image.getWidth() - zoomFactor / 2 + offsetX;
    double i = y * zoomFactor / image.getHeight() - zoomFactor / 2 + offsetY;
    double zr = 0, zi = 0;
    int iter;
    for (iter = 0; iter < maxIter; iter++) {
      double nzr = zr * zr - zi * zi + r;
      double nzi = 2 * zr * zi + i;
      if (nzr * nzr + nzi * nzi > escapeRadius * escapeRadius)
        break;
      zr = nzr;
      zi = nzi;
    }
    image.setRGB(x, y, Color.HSBtoRGB(0.5f * iter / maxIter, 1.0f, 1.0f));
  }
}


我修改过的,更干净的代码:

for (int x = xStart; x <= xEnd; x++) {
  for (int y = yStart; y <= yEnd; y++) {
    z1 = new ComplexNumber(x * dx - zoomFactor / 2 + offsetX,
                           y * dy - zoomFactor / 2 + offsetY);
    z0 = new ComplexNumber(0,0);
    int iter;
    for (iter = 0; iter < maxIter; iter++) {
      nz = cAdd(cMult(z0,z0),z1);
      if (cAbs(nz) > escapeRadius )
        break;
      z0 = nz;
    }
    image.setRGB(x, y, Color.HSBtoRGB(0.5f * iter / maxIter, 1.0f, 1.0f));
  }
}


我唯一的问题是如何在定义z1和z0的两行上摆脱“ new”。似乎我在浪费大量的内存,因为在上面的代码块的近25,000次执行中,两个对象总共“更新”了1,000,000+次,尽管没有问题。

我知道我至少需要在该方法内使用一次new,但是如果我将语句(如下所示)放在循环之外(以及在render()内或之外),如果我在定义z1的这两行中省略了new上面的代码块中的z0和z0,我得到了错误
“找不到符号:方法ComplexNumber(double,double)位置:类MandelbrotTask。”

z1 = new ComplexNumber();
z0 = new ComplexNumber();


----编辑10:21 12/26/13

这是被调用的ComplexNumber类的一部分。构造函数调用ComplexNumber()realimag二进制部分设置为0。

class ComplexNumber {
  public double real;
  public double imag;

  public ComplexNumber() {
    real = 0.0;
    imag = 0.0;
  }

  public ComplexNumber(double r, double i) {
    this.real = r;
    this.imag = i;
  }

    public static ComplexNumber cAdd(ComplexNumber a, ComplexNumber b) {
    return new ComplexNumber(a.real + b.real, a.imag + b.imag);
  }

  public static ComplexNumber cMult(ComplexNumber a, ComplexNumber b) {
   return new ComplexNumber(a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real);
  }

  public static double sqr(double x) {
    return x * x;
  }

  public static double cAbs(ComplexNumber z) {
    return Math.sqrt(sqr(z.real) + sqr(z.imag));
  }

}

最佳答案

得到了一些好评,因此我将自己的评论转换为答案。如果要避免在循环中反复实例化,唯一的出路是为ComplexNumber类创建setter方法:

public void setReal(double real) { this.real = real; }
public void setImaginary(double im) { this.im = im; }
public void setTo(double real, double im) { setReal(real); setImaginary(im); }


我假设您的课程有称为realim的字段。

此外,如果您不能修改类本身,则应通过创建形式为class MyComplexNumber extends ComplexNumber的包装器类来扩展它,然后为MyComplexNumber实现setter方法。

09-05 03:11