多年来,The Mandelbrot set 一直是我的最爱。几年前,我已经在Pascal上成功创建了它,最近又在TI-83图形计算器上成功创建了它(Java使其更快地成熟了)。
由于涉及到复数,因此我从使用extends RecursiveAction
和BufferedImage
的ForkJoinPool
文本中获取了一个版本(不了解这些概念和总体实现),并使用了我几个月前开发的例程进行了修改(进行点绘图的代码,使它看起来更像是复数。
原版的:
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()
将real
和imag
二进制部分设置为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); }
我假设您的课程有称为
real
和im
的字段。此外,如果您不能修改类本身,则应通过创建形式为
class MyComplexNumber extends ComplexNumber
的包装器类来扩展它,然后为MyComplexNumber实现setter方法。