• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

Does Java handle complex numbers?

NintendoMan07

Smash Journeyman
Joined
Jul 23, 2008
Messages
251
Location
Dallas: The Land that Killed Me
This is a question that just suddenly hit me as I prepared to do a project over fractals. If Java CAN use complex numbers, I'm fine. If not, well, I could be in a terrible predicament.

If someone could give me a prompt response, I'd greatly appreciate it.

EDIT: I apologize for the inconvenience, I just NOW found the answer. It looks like everything imaginary becomes NaN. What a bummer.
 

AltF4

BRoomer
BRoomer
Joined
Dec 13, 2005
Messages
5,042
Location
2.412 – 2.462 GHz
Just google it, dude. I searched for "java complex numbers" and got pages of valid results. There are custom libraries, and more official ones. You can't just take the square root of a negative number and expect Java to handle it, though. What did you expect?
 

AltF4

BRoomer
BRoomer
Joined
Dec 13, 2005
Messages
5,042
Location
2.412 – 2.462 GHz
It's going to depend on how much processing you need to do on the complex numbers. If you need to do a lot of operations on them, then use one of the libraries online. If you don't need to do a whole lot with them (adding and subtracting at most) then you can probably get away with implementing it yourself.
 

NintendoMan07

Smash Journeyman
Joined
Jul 23, 2008
Messages
251
Location
Dallas: The Land that Killed Me
Well, in short, I'm trying to plot the Mandlebrot Set.

http://en.wikipedia.org/wiki/Mandlebrot_set

At the time I had created this thread, I recalled that the Mandlebrot set is plotted in the complex plane, which naturally led me to make the thread.

However, the section of pseudocode partway through caught my eye:

Code:
For each pixel on the screen do:
{
  x = x0 = x co-ordinate of pixel
  y = y0 = y co-ordinate of pixel

  iteration = 0
  max_iteration = 1000
 
  while ( x*x + y*y <= (2*2)  AND  iteration < max_iteration ) 
  {
    xtemp = x*x - y*y + x0
    y = 2*x*y + y0

    x = xtemp

    iteration = iteration + 1
  }
 
  if ( iteration == max_iteration ) 
  then 
    color = black
  else 
    color = iteration

  plot(x0,y0,color)
}
I tried to adapt this to my Java program, but plotting the actual points seems to be the issue I'm having problems with.

I'm not sure if this is a good way to go about this, but I'm implementing this in a JPanel subclass that's using the paintComponent method for the plot currently. Unfortunately, reworking the coordinate system to fit what I'm plotting is a puzzle in itself.

This is one of those moments where I feel like I'm terrible at this.
 

Big Sean

Smash Journeyman
Joined
Jun 3, 2003
Messages
484
Location
Berkeley
Although Kirby King's answer is of course the coolest :) , after looking at the site some more I realized that there is really no imaginary arithmetic needed. Take a look at the derivation below the pseudocode and you'll see that that Imaginary arithmetic has already been taken care of for you. All thats left is simple real integer arithmetic.

Edit: oh wait its the plotting right? Yeah I wouldn't be too stressed by it, pixel perfect drawing at runtime isn't a thing people do very often. What you need is the BufferedImage class. So when you call plot what you actually call is setRGB on the buffered image. After the algorithm is done the BufferedImage can be used as any other image so next time paintComponent is called you only have to call drawImage on the graphics object with your BufferedImage as the image. Any other questions just let us know.
 

NintendoMan07

Smash Journeyman
Joined
Jul 23, 2008
Messages
251
Location
Dallas: The Land that Killed Me
I guess I'll need some extra help with this. This is what I have:

Code:
public class MandlebrotSet extends JFrame
	{
		private DrawingPane dPane = new DrawingPane();
		
		public MandlebrotSet()
		{
			//Add the DrawingPane object to the frame.
			add(dPane);
			dPane.repaint();
		}
		
		class DrawingPane extends JPanel
		{
			// Create the BufferedImage object.
			// (I didn't know what to use for the last argument, and evidently from the stack trace the exception originates here)
			private BufferedImage mandlebrot = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
			
			protected void paintComponent(Graphics g)
			{
				super.paintComponent(g);
				
				// Find the center of the component.
				int shiftx = getWidth() / 2;
				int shifty = getHeight() / 2;
				
				// Start from the top-left of the component.
				Point p = new Point(0, 0);
				
				// Plot from top-to-bottom left-to-right.
				// (Section adapted from the pseudocode on the Wikipedia page: http://en.wikipedia.org/wiki/Mandlebrot_set).
				while(p.y <= getHeight())
				{
					while(p.x <= getWidth())
					{
						//Adjust for calculating the point series.
						int x = p.x - shiftx;
						int y = shifty - p.y;
						
						//Set the bounds for iterating.
						int iterationnum = 0;
						int maxiteration = 1000;
						
						//Calculate the series of points.
						while (x*x + y*y <= (2*2) && iterationnum < maxiteration)
						{
							int xtemp = x*x - y*y + p.x;
							y = 2*x*y + p.y;
							
							x = xtemp;
							
							iterationnum++;
						}
						
						// If the point series did not escape the bounds within the number of iterations, paint the point black, else cyan.
						// (I'm considering expanding beyond the binary coloring system. This would simply be a matter of chaining if-else-if statements, right?)
						if(iterationnum == maxiteration)
						{
							g.setColor(Color.BLACK);
						}
						else
						{
							g.setColor(Color.CYAN);
						}
						
						// Plot the point.
						plot(p.x, p.y, g.getColor());
						p.x++;
					}
					
					// Increment y and start from the left again.
					p.y++;
					p.x = 0;
				}
				
				// Draw the image.
				// (I'm unfamiliar with the proper implementation of this. Does this seem right?)
				g.drawImage(mandlebrot, 0, 0, Color.GREEN, this);
			}
			
			private void plot(int xpoint, int ypoint, Color c)
			{
				mandlebrot.setRGB(xpoint, ypoint, c.getRGB());
			}
		}
	}
It's currently throwing an exception over my implementation of the BufferedImage class, so I'll try to look into what's wrong there, but other than that, I don't know what it looks like yet. It was only "plotting" one point before (before I tried Cursive's suggestion), so I don't know if this is a problem with the loop or if it'll be fixed with BufferedImage.
 

Big Sean

Smash Journeyman
Joined
Jun 3, 2003
Messages
484
Location
Berkeley
It looks good so far. What I expect it to look like is all cyan and like a few black dots here and there. If you want a simple grayscale image one way to do so would be to multiply the iteration by 255 / max_iteration. That value would be the R, G, and B values. An exponential or logarithmic one might look pretty cool too. A cool way also is to pick a bunch of colors up to max_iteration, store them in an array and do a lookup for the iteration in the array. I think what would be a pretty cool one would be to keep red 255 and perform exponential scaling on the blue and green values. But experiment i'm sure there are even cooler things.
 

NintendoMan07

Smash Journeyman
Joined
Jul 23, 2008
Messages
251
Location
Dallas: The Land that Killed Me
Despite the fact that it might look good, it actually doesn't work, and this is the problem I'm having.

I've hunted around on this subject (plotting points) and found some ideas to try, but so far none of those ideas have actually worked. Really, it's hard for me to claim that I know what I'm doing when I really don't.

EDIT: My roommate and I figured out stuff and got it semi-working now. HOWEVER, what shows up is NOT the intended result.

For reference, here's the updated code:

Code:
public class MandlebrotSet extends JFrame
	{
		private DrawingPane dPane = new DrawingPane();
		
		public MandlebrotSet()
		{
			//Add the DrawingPane object to the frame.
			add(dPane);
			dPane.repaint();
		}
		
		class DrawingPane extends JPanel
		{
			// Create the BufferedImage object.
			private BufferedImage mandlebrot;
			
			protected void paintComponent(Graphics g)
			{
				super.paintComponent(g);
				
				mandlebrot = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
				
				// Find the center of the component.
				int shiftx = getWidth() / 2;
				int shifty = getHeight() / 2;
				
				// Start from the top-left of the component.
				Point p = new Point(0, 0);
				
				// Plot from top-to-bottom left-to-right.
				// (Section adapted from the pseudocode on the Wikipedia page: http://en.wikipedia.org/wiki/Mandlebrot_set).
				while(p.y < getHeight())
				{
					while(p.x < getWidth())
					{
						//Adjust for calculating the point series.
						int x = p.x - shiftx;
						int y = shifty - p.y;
						
						//Set the bounds for iterating.
						int iterationnum = 0;
						int maxiteration = 1000;
						
						//Calculate the series of points.
						while (x*x + y*y <= (2*2) && iterationnum < maxiteration)
						{
							int xtemp = x*x - y*y + p.x;
							y = 2*x*y + p.y;
							
							x = xtemp;
							
							iterationnum++;
						}
						
						// If the point series did not escape the bounds within the number of iterations, paint the point black, else cyan.
						// (I'm considering expanding beyond the binary coloring system. This would simply be a matter of chaining if-else-if statements, right?)
						if(iterationnum == maxiteration)
						{
							g.setColor(Color.BLACK);
						}
						else
						{
							g.setColor(Color.CYAN);
						}
						
						// System.out.println(p.x + "," + p.y);
						
						// Plot the point.
						plot(p.x, p.y, g.getColor());
						p.x++;
						
					}
					
					// Increment y and start from the left again.
					p.y++;
					p.x = 0;
				}
				
				// Draw the image.
				// (I'm unfamiliar with the proper implementation of this. Does this seem right?)
				g.drawImage(mandlebrot, 0, 0, Color.GREEN, this);
			}
			
			private void plot(int xpoint, int ypoint, Color c)
			{
				mandlebrot.setRGB(xpoint, ypoint, c.getRGB());
			}
		}
	}
EDIT++: Well, I now know that it'll take an abnormally large number on both the iterations and the circular bound to see ANY black at all. I'm just not entirely sure of what I SHOULD expect. No offense, but... I kinda wanted that awesome spiky glob instead of just a spread of dots.
 

Big Sean

Smash Journeyman
Joined
Jun 3, 2003
Messages
484
Location
Berkeley
Okay i'm pretty much going to repeat what I said before because its still the same issue.

Code:
if(iterationnum == maxiteration)
{
	g.setColor(Color.BLACK);
else
{
	g.setColor(Color.CYAN);
}
This right here is your issue. As you explained reaching a maxiteration is incredibly rare event. This means that what you should expect is all cyan, and few black dots, which sounds like exactly what your getting. Now if you want to keep this a binary image what I would suggest is to call in the constructor something like this:
Code:
private int maxIteration;
for(int i = 1; i < 1000; ++i) {
    maxiteration = i;
    System.out.println("Max Iteration: " + i);
    repaint();
    Thread.sleep(50);
}
This code assumes now that maxIteration is no longer a local variable but a private field. The point of this code is so you can check out a suitable maxIteration that will make your fractal look awesome. Now what wikipedia suggests is something different. They suggest to do something like this:

Linear Case:
Code:
int val = (255 * iterationnum) / maxiteration;
g.setColor(Color(val, val, val));

Exponential Case:
Code:
int val = 255 * ((int) math.exp(maxiteration - iterationnum) - 1);       
g.setColor(Color(val, val, val));
Logarithmic Case:
Code:
int val = 255 * ((int) (math.log(iterationnum) / math.log(maxiteration));       
g.setColor(Color(val, val, val));
Cursives Suggestion A:
Code:
int val = 255 * ((int) math.exp(maxiteration - iterationnum) - 1);       
g.setColor(Color(255, val, val));
Cursives Suggestion B:
Code:
int val = 255 * ((int) (math.log(iterationnum) / math.log(maxiteration));       
g.setColor(Color(255, val, val));
Wikipedia also suggests way more complicated ones, but I have a feeling that if you try these 5 along with the while loop to find suitable maxiterations, your going to find something really cool, I guarantee it, or your money back :)
 

NintendoMan07

Smash Journeyman
Joined
Jul 23, 2008
Messages
251
Location
Dallas: The Land that Killed Me
Well, thanks for all the help, Cursive.

It still isn't quite right, but I figure if I haven't fixed it by now, I probably won't be able to fix it quickly.

I've got the program to where I'm able to adjust the maximum number of iterations and the "bailout" number (the squared value in other part of the while loop's condition), and playing around with it gets some okayish results, but it's definitely not the real deal.

Iterations = 1000, Bailout = 2 gets me an all-black graph
Iterations = 1, Bailout = 2 gets me the same thing
Iterations = 5, Bailout = 200 gets me a circular gray area with two lighter blobs in the center

Well, it was worth trying out anyway. BTW, I used the linear situation for the coloring.
 

Big Sean

Smash Journeyman
Joined
Jun 3, 2003
Messages
484
Location
Berkeley
Oh man that sucks. I'll run it on my computer a little bit later and see if I can debug it for real.
 

NintendoMan07

Smash Journeyman
Joined
Jul 23, 2008
Messages
251
Location
Dallas: The Land that Killed Me
Hm, this still isn't working out, AT ALL.

Obviously staring at it does nothing, but I can't exactly figure out what change I could make to get the correct picture.

I haven't really changed it much from the code I posted previously, other than applying Cursive's suggestion with the coloring scheme.

EDIT: I finally found working code here.

Regardless, I'd still like to figure out what went wrong with mine. I could finally "R.I.P." if I could figure that out.

Also, how does a programmer typically cite other source code used? So far I've just been going off of intuition when citing, but I'm sure there's a universally "proper" way to do that, right?
 
Top Bottom