The Golden Ratio

Also known as the “Divine Quotient”, the Golden Ratio was given an almost magical meaning during the renaissance, but it’s actually much older than that. Leonardo DaVinci used it. Euclid used it. It was supposedly discovered by Pythagoras. So, what is it? It’s very simple. Take a length and divide it into two parts: a and b:

When the ratio between a and b is equal to the ratio between a+b and a, then you have the Golden Ratio. The value of the Golden Ratio is:

Why is it so special? Because if you know about it, it can be seen in many different places; in geometrical figures, in architecture, in paintings, and in nature. I’ll show you. Draw a pentagon:

Pentagon

Draw straight lines between all vertices of the pentagon. This will result in a pentagram (five-pointed star). Now mark the lengths a and b as this picture shows:

Pentagram inside pentagon

Guess what the ratio is between the lengths a and b? The Golden Ratio. Now, mark two other lengths a' and b':

Pentagram inside pentagon with other lengths

You guessed it. The ratio between a' and b' is the Golden Ratio.

It’s actually pretty easy to approximate Phi (φ), as the Golden Ratio normally is called. Take any two numbers and add them, then divide the sum with the larger number. For example, 11 and 74:

11.0+74.0=85.0
85.0/74.0=1.1486486486486487

Now we add the larger of the numbers (74) to the sum (85), and then we again divide the new sum (159) with the the previous sum (85):

74.0+85.0=159.0
159.0/85.0=1.8705882352941177

We’re getting there. One more time:

85.0+159.0=244.0
244.0/159.0=1.5345911949685536

No, this is too tedious. Let’s write a program that does it. For no reason whatsoever, I’ll pick Scala. What is Scala? I’m on a Mac, so I’ll just do:

% port info scala
scala @2.7.5 (lang, java)

Description:          Scala is a modern multi-paradigm programming language designed to express common programming patterns
                      in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and
                      functional languages. It runs inside a Java Virtual Machine and is fully interoperable with Java.
Homepage:             http://www.scala-lang.org/

This is how I install Scala:

% sudo port install scala

I’ll want some editor support, so I install the TextMate bundle that accompanies Scala:

% cd /Library/Application Support/TextMate/Bundles/
% unzip /opt/local/share/scala/misc/scala-tool-support/textmate/Bundles/Scala.tmbundle.zip

I’ll tell TextMate to reload its bundles by selecting the menu “Bundles | Bundle Editor | Reload Bundles”. Now I’m all set.

Consider this Scala program (phi1.scala):

var x = 11.
var y = 74.

for (i <- 1 to 5) {
    var sum = x + y
    var q = sum / y
    println(q)
    x = y
    y = sum
}

I’ll run it like this:

% scala phi1.scala
1.1486486486486487
1.8705882352941177
1.5345911949685536
1.651639344262295
1.6054590570719602

It’s not pretty, but it does the job. Let’s spice it up with some input arguments and better printout (phi2.scala):

var x = 11.
var y = 74.
var n = 13

if (args.length > 3) {
    println("Usage: scala phi2.scala [n [x [y]]]")
    println("  n: number of times to perform calculation (default: " + n + ")")
    println("  x: start value of 'x' (default: " + x + ")")
    println("  y: start value of 'y' (default: " + y + ")")
    System.exit(1)
}
if (args.length >= 1) n = Integer.parseInt(args(0))
if (args.length >= 2) x = Integer.parseInt(args(1))
if (args.length == 3) y = Integer.parseInt(args(2))

for (i <- 1 to n) {
    var sum = x + y
    print(i + ": " + x + "+" + y + "=" + sum)
    var q = sum / y
    println(", " + sum + "/" + y + "=" + q)
    x = y
    y = sum
}

I’ll run it with four arguments to test it:

% scala phi2.scala 1 2 3 4
Usage: scala phi2.scala [n [x [y]]]
  n: number of times to perform calculation (default: 13)
  x: start value of 'x' (default: 11.0)
  y: start value of 'y' (default: 74.0)

I won’t bore you with more tests, but instead do what we intended to do from the start: have a program run the iterations for us. I’ll run it with no arguments, using the defaults:

% scala phi2.scala
1: 11.0+74.0=85.0, 85.0/74.0=1.1486486486486487
2: 74.0+85.0=159.0, 159.0/85.0=1.8705882352941177
3: 85.0+159.0=244.0, 244.0/159.0=1.5345911949685536
4: 159.0+244.0=403.0, 403.0/244.0=1.651639344262295
5: 244.0+403.0=647.0, 647.0/403.0=1.6054590570719602
6: 403.0+647.0=1050.0, 1050.0/647.0=1.6228748068006182
7: 647.0+1050.0=1697.0, 1697.0/1050.0=1.6161904761904762
8: 1050.0+1697.0=2747.0, 2747.0/1697.0=1.618738951090159
9: 1697.0+2747.0=4444.0, 4444.0/2747.0=1.6177648343647615
10: 2747.0+4444.0=7191.0, 7191.0/4444.0=1.618136813681368
11: 4444.0+7191.0=11635.0, 11635.0/7191.0=1.6179947156167431
12: 7191.0+11635.0=18826.0, 18826.0/11635.0=1.6180489901160293
13: 11635.0+18826.0=30461.0, 30461.0/18826.0=1.6180282587910337

Actually, I will run one more test, but this time I’ll choose the starting values more carefully. One of many wonderful properties of the Fibonacci series is that the ratio between the numbers is very close to the Golden Ratio. This means it will converge much quicker. Check this out, four correct decimals after just four iterations:

% scala phi2.scala 4 21 34
1: 21.0+34.0=55.0, 55.0/34.0=1.6176470588235294
2: 34.0+55.0=89.0, 89.0/55.0=1.6181818181818182
3: 55.0+89.0=144.0, 144.0/89.0=1.6179775280898876
4: 89.0+144.0=233.0, 233.0/144.0=1.6180555555555556

Here is the final version, with some stuff that makes the file executable (phi.scala):

#!/bin/sh
exec scala $0 $@
!#
var x = 11.
var y = 74.
var n = 13

if (args.length > 3) {
    println("Usage: scala phi.scala [n [x [y]]]")
    println("  n: number of times to perform calculation (default: " + n + ")")
    println("  x: start value of 'x' (default: " + x + ")")
    println("  y: start value of 'y' (default: " + y + ")")
    System.exit(1)
}
if (args.length >= 1) n = Integer.parseInt(args(0))
if (args.length >= 2) x = Integer.parseInt(args(1))
if (args.length == 3) y = Integer.parseInt(args(2))

for (i <- 1 to n) {
    var sum = x + y
    print(i + ": " + x + "+" + y + "=" + sum)
    var q = sum / y
    println(", " + sum + "/" + y + "=" + q)
    x = y
    y = sum
}

I’ll make it executable and run it:

% chmod +x phi.scala
% ./phi.scala 10 13 21
1: 13.0+21.0=34.0, 34.0/21.0=1.619047619047619
2: 21.0+34.0=55.0, 55.0/34.0=1.6176470588235294
3: 34.0+55.0=89.0, 89.0/55.0=1.6181818181818182
4: 55.0+89.0=144.0, 144.0/89.0=1.6179775280898876
5: 89.0+144.0=233.0, 233.0/144.0=1.6180555555555556
6: 144.0+233.0=377.0, 377.0/233.0=1.6180257510729614
7: 233.0+377.0=610.0, 610.0/377.0=1.6180371352785146
8: 377.0+610.0=987.0, 987.0/610.0=1.618032786885246
9: 610.0+987.0=1597.0, 1597.0/987.0=1.618034447821682
10: 987.0+1597.0=2584.0, 2584.0/1597.0=1.6180338134001253

Check out Golden Ratio on Wikipedia for more details.

This Post Has One Comment

  1. I had expected some Scala wizards to criticize my feeble attempt at coding an algorithm in Scala, but it didn’t happen. So I’ll do it myself instead.

    What do I really want to do? If n is 1, the larger number should be divided by the smaller number. Otherwise, calculate the sum of the numbers and repeat on the larger number and the sum, for one less iteration.

    I’ll start the interactive Scala shell and type this in:

    scala> def phi(a:Double, b:Double, n:Int): Double = n match {
    | case 1 => (a max b)/(a min b)
    | case _ => phi((a max b), a+b, n-1)
    | }
    phi: (Double,Double,Int)Double

    Testing it, and what do you know? It works:

    scala> phi(5., 8., 20)
    res1: Double = 1.618033988957902

Leave a Reply

Close Menu