# The Most Irrational of Numbers

Today I have a new interactive demonstration for you!

Controls
Zoom in: W
Zoom out: S
Reset angle: 0
Switch mode (auto or user): Space
On “User Mode”:
– Increase angle: Up
– Decrease angle: Down

[pjs4wp]
void setup() {
size(600,600);
background(0);
stroke(255);
fill(255);
}
float r = 2;
float da = 0;
float dda = .0001;
boolean autoPlay = true;
void draw() {
background(0);
text(“Angle = ” + (float)((int)(da*10000))/100. + “%”, width/2, 20);
text(“Zoom = ” + (float)((int)(r*100))/100., width/2, 35);
if (autoPlay)
text(“Mode: Auto”, width/2, 50);
else
text(“Mode: User”, width/2, 50);
translate(width/2,height/2);
int i = 0;
float angle = 0;
while (width/r > i) {
float x = r*i*cos(angle);
float y = r*i*sin(angle);
ellipse(x,y,5,5);
angle += 2*PI*da;
i++;
}
if (keyPressed) {
if (key == ‘w’)
r *= 1.01;
if (key == ‘s’)
r *= .99;
if (key == ‘0’)
da = 0;
if (!autoPlay) {
if (keyCode == UP)
da += dda;
if (keyCode == DOWN)
da -= dda;
}
}
if (autoPlay)
da += dda;
}
void keyReleased() {
if (key == ‘ ‘)
autoPlay = 1 – autoPlay;
}
[/pjs4wp]

(As always, zooming out too much will make things begin to lag. Also, fair warning, things start getting a little seizure-inducing around a zoom of .5 or less.)

Okay! Pretty, right? But what’s actually going on?

Each frame we are drawing a sequence of dots. We start at the center of the screen, and take constant radial steps outwards. And for each step, we apply some fixed angular rotation. This angular rotation is given as a percentage of 2π on the top of the screen, and is the thing being adjusted frame by frame (either automatically or based on your input, depending on which mode you choose).

What’s cool is what happens when you approach simple rational numbers. Take a look for yourself by going on “User” mode and bringing the angle to 10% (for 1/10), 14.28% (for 1/7), 25% (for 1/4), and so on. Here are two examples:

Cool, right? At every rational number, we end up with a number of “spokes” corresponding to the denominator of our rational number. People sometimes describe the golden ratio Ф as the “most irrational number”, meaning that in some sense it is the most difficult to approximate by rational numbers. How does this look on our visualization? Check it out!

And zooming out further, we see…

We can see that using Ф as our angular rotation gives us the “least spokey” shape possible. As we zoom out further and further, we will always see our points looking basically evenly distributed across the angles at any given radius. This is a wonderfully visual way to understand the irrationality of Ф!

# Hopping Midpoints

Put down three points on a piece of paper. Choose one of them as your “starting point”. Now, randomly choose one of the three points and hop from your starting point, halfway over to the chosen point. Mark down where you’ve landed. Then repeat: randomly choose one of the three starting points, and move halfway from your newly marked point to this new chosen point. Mark where you land. And on, and on, to infinity.

What pattern will arise? Watch and see!

Controls:
E to increase points/second.
Q to decrease points/second.
Click and drag the red points to move them around.
Pressing a number key will make a polygon with that number of sides.
[pjs4wp]
float N = 3;
float[] X = new float(N);
float[] Y = new float(N);
float radius = 600/2 – 20;
float i = 0;
while (N > i)
{
X[i] = radius * cos(2*PI*i/N – PI/2 + 2*PI/N);
Y[i] = radius * sin(2*PI*i/N – PI/2 + 2*PI/N);
i += 1;
}
float xNow = X[0];
float yNow = Y[0];
float speed = 1;
int selected = -1;
void setup()
{
size(600,600);
frameRate(10);
background(0);
}
void draw()
{
fill(255);
stroke(255);
text((str)(speed*10) + ” points / second\nE to speed up\nQ to slow down\nClick and drag red points!”,15,25);
translate(width/2, height/2);
float i = 0;
while(i < speed) { point(xNow, yNow); index = (int)(random(N)); xNow = (xNow + X[index])/2; yNow = (yNow + Y[index])/2; i += 1; } stroke(color(255,0,0)); fill(color(255,0,0)); float j = 0; while (N > j)
{
ellipse(X[j],Y[j],10,10);
j += 1;
}
}
void keyReleased()
{
bool reset = 0;
if (key == ‘e’) speed *= 10;
else if (key == ‘q’ && speed > 1) speed /= 10;
else if (key == ‘2’) N = 2;
else if (key == ‘3’) N = 3;
else if (key == ‘4’) N = 4;
else if (key == ‘5’) N = 5;
else if (key == ‘6’) N = 6;
else if (key == ‘7’) N = 7;
else if (key == ‘8’) N = 8;
else if (key == ‘9’) N = 9;
else reset = 1;
if (reset == 0)
{
background(0);
float i = 0;
while (N > i)
{
X[i] = radius * cos(2*PI*i/N – PI/2);
Y[i] = radius * sin(2*PI*i/N – PI/2);
i += 1;
}
xNow = X[0];
yNow = Y[0];
}
}
void mousePressed()
{
if (selected == -1)
{
float i = 0;
while (N > i)
{
if ((X[i] + 5 >= mouseX – width/2) && (mouseX – width/2 >= X[i] – 5))
if ((Y[i] + 5 >= mouseY – height/2) && (mouseY – height/2 >= Y[i] – 5))
selected = i;
i += 1;
}
}
}
void mouseReleased()
{
if (selected != -1)
{
X[selected] = mouseX – width/2;
Y[selected] = mouseY – height/2;
selected = -1;
xNow = X[0];
yNow = Y[0];
background(0);
}
}
[/pjs4wp]

# Exploring Julia Sets

Here’s a natural follow-up to my last post on the Mandelbrot set – an interactive Julia set explorer!

The Julia set corresponding to a particular point c = x + iy in the complex plane is defined as the set of complex numbers z that stay finite upon arbitrary iterations of the following function: fc(z) = z2 + c. The Mandelbrot set, by comparison, is defined as the set of complex numbers c such that the value obtained by starting with 0 and iterating the function fc arbitrarily many times converges.

What’s remarkable is now beautiful and complex the patterns that arise from this simple equation are. Take a look for yourself: just hover over a point to see its corresponding Julia set!

[pjs4wp]
float xmin = -1.8;
float xmax = 1.8;
float ymin = -1.2;
float ymax = 1.2;
float resolution = 30;
void setup()
{
size(600,400);
background(0);
stroke(255);
}
void draw()
{
background(0);
float cx = xmin + (xmax-xmin)*(float)(mouseX)/(float)(width);
float cy = ymin + (ymax-ymin)*(float)(mouseY)/(float)(height);
drawJuliaSet(cx, cy);
stroke(255);
fill(255);
line(-xmin*width/(xmax-xmin),0,-xmin*width/(xmax-xmin),height);
line(0,-ymin*height/(ymax-ymin),width,-ymin*height/(ymax-ymin));
}
void keyPressed()
{
if (key == ‘e’) resolution += 10;
if (key == ‘q’) resolution -= 10;
if (key == ‘ ‘) resolution = 30;
}
void drawJuliaSet(float cx, float cy)
{
text(“(” + (str)((int)(cx*100)/100.) + “,” + (str)(-(int)(cy*100)/100.) + “)”, 20, 20);
float i = 0;
float j = 0;
while (height > j)
{
x = xmin + (xmax-xmin)*(float)i/width;
y = ymin + (ymax-ymin)*(float)j/height;
float step = 0;
while (step < resolution) { float xNew = x*x - y*y + cx; y = 2*x*y + cy; x = xNew; if (x*x + y*y > 4) break;
step += 1;
}
stroke(color(0,255,0));
fill(color(0,255,0));
if (4 > x*x + y*y) point(i,j);
i += 1;
if (i == width)
{
i = 0;
j += 1;
}
}
stroke(0);
fill(color(255,0,0));
ellipse((cx-xmin)*width/(xmax-xmin),(cy-ymin)*height/(ymax-ymin),10,10);
}
[/pjs4wp]
Resolution is preset at a value good for seeing lots of details and loading at a reasonable speed, but should you want to change it, controls are ‘E’ to increase it and ‘Q’ to decrease it. To reset to default, press ‘SPACE’.