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()
内部或外部),如果我省略{{ 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
答案 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); }
我假设您的班级有real
和im
字段。
此外,如果你不能修改类本身,你应该通过创建一个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 =新的复合体......不起作用,但我会考虑回复。
(我刚刚意识到我“学到了”我已经“知道”的东西。一直都会发生。)