没有“新”,不能使用我的“类型”ComplexNumber - 为什么?

时间:2013-12-27 02:49:58

标签: java new-operator

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

由于涉及复数,我从extends RecursiveAction使用BufferedImageForkJoinPool的文本中获取了一个版本(不了解这些概念和整体实现),并使用例程几个月前我开发了一个修改(哎呀)执行点绘图的代码,这样看起来更像复杂的数字。

原件:

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()内部或外部),如果我省略{{ 1}}从上面代码块中定义z1和z0的那两行,我得到了错误 “找不到符号:方法ComplexNumber(double,double)位置:类MandelbrotTask。”

new

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

以下是Invovled的ComplexNumber类的一部分。构造函数调用z1 = new ComplexNumber(); z0 = new ComplexNumber(); ComplexNumber()real - 部分设置为0。

imag

3 个答案:

答案 0 :(得分:2)

得到一些赞成票,所以我将我的评论转换成答案。如果您想避免在循环内反复重新实例化,那么唯一的出路就是为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方法。

答案 1 :(得分:0)

类型很好,但如果您的问题是记忆,我认为不需要它们。

尝试在ComplexNumber中创建方法,例如

public void init(){
  //clear and reset all variables inside ComplexNumber
  ...
}

public void set(param1, param2...){
  //set required variables
  ...
}

然后分别在循环中使用set()和init(),而不是每次都创建一个新实例。如果您不需要引用循环内创建的对象,则此方法有效。

答案 2 :(得分:0)

我应该提前指出​​以下代码 - 没有new,没有设置者 - 完成任务:

    z1.real = x * dx - zoomFactor / 2 + offsetX;
    z1.imag = y * dy - zoomFactor / 2 + offsetY;
    z0.real = 0;
    z0.imag = 0;

我只是希望得到与原始修订代码类似的内容,每个复数的一行。

====================

这是我将ComplexNumber类扩展为RealNumber类(看起来有点落后,但是......):

class RealNumber extends ComplexNumber 
{  // RealNumber IS-A subclass ...

  RealNumber() {}

  RealNumber(double r) {
    super.imag = 0;                         // ... THIS kind of subclass ... 
    super.real = r;                         // ... of ComplexNumber!           
  }
}

============================

嘿,@ Chthonic,这很有效:

public void setReal(double real) { this.real = real; }
public void setImaginary(double imag) { this.imag = imag; }
public void makeComplex(double real, double imag) { setReal(real); setImaginary(imag); }  

...

    z1 = new ComplexNumber();
    z0 = new ComplexNumber(); // before loop

...

    z1.makeComplex(x * dx - zoomFactor / 2 + offsetX,y * dy - zoomFactor / 2 + offsetY);
    z0.makeComplex(0, 0);

感谢这个想法。我不确定我到底为什么我的原始z1 =新的复合体......不起作用,但我会考虑回复。

(我刚刚意识到我“学到了”我已经“知道”的东西。一直都会发生。)