Calculations

The algorithm for the OpenPostcode is actually very straightforward. It defines an origin in the North-West, defines the height and width of the island and then uses a 5x5 grid to define areas. Each character, from left to right, defines a further 5x5 grid inside the last. The logo here illustrates the pattern and could even be used to estimate locations; however the precise mathematics is a simple use of base-25 and base-5 numbering.

Helpfully, a base-25 number is the square of 5. So any grid reference inside a 5x5 grid can be referenced as two numbers; 0 to 4, and 0 to 4. Lets for example go for latitude 2 and longitude 3. That's 2 and 3 - or even just write it as "23". Now the benefit of using base-25 comes into play. Treat this as a base-5 number and convert it to a base-25 number and you are left with a single character encoding both coordinates. 23 as a base-5 number in ordinary decimal is just 2x5+3=13, which is D in base-25. The reverse is as simple. Keep doing this with more characters and you can reference positions on a national scale to a high degree of accuracy with little calculation and compact codes. (OPC Version 3, 17th April, 2012)

Conversion from Coordinates to OpenPostcode

e.g. Spire of Dublin 53.349795, -6.260254 (using coordinates as quoted in Wikipedia, Google imagery may vary from the exact location).
  1. First compare the location to the origin of the island as defined by the parameters: West -10.75, North 55.5.
    • 55.5-53.349795 = 2.150205
    • 10.75-6.260254 = 4.489746
  2. Then scale to percentage of the boundaries of the island by the parameters: wide=5.4, high=4.2.
    • 2.150205/4.2 = 0.511953571
    • 4.489746/5.4 = 0.831434444
  3. The highest scale possible is defined by the number of possible characters and number of code digits: "23456789CDFGHJKLMNPQRTVWX" and 8.
    • "23456789CDFGHJKLMNPQRTVWX" gives 25 characters. The square-root of 25 is 5 (allowing a base-5 encoding of longitude and latitude in a single character). The maximum scale is therefore 5^8 digits = 390625.
    • int(0.511953571*390625) = 199981
    • int(0.831434444*390625) = 324779
  4. Convert to base-5. While many languages have functions for conversion, even where no function is preprogrammed it is relatively trivial to convert from one base to base. In a spreadsheet conversion for example "=MOD(INT(Num/Base^7),Base) &MOD(INT(Num/Base^6),Base) &MOD(INT(Num/Base^5),Base) &MOD(INT(Num/Base^4),Base) &MOD(INT(Num/Base^3),Base) &MOD(INT(Num/Base^2),Base) &MOD(INT(Num/Base),Base) &MOD(Num,Base)".
    • base10to5(199981) = 22344411
    • base10to5(324779) = 40343104
  5. Digit by digit, calculate a base-25 combined character from the latitude and longitude. In maths, each digit is easily isolated as: int((number mod base^position)/base^(position-1)).
    • 2*5+4 = 14; 14 in base 25 is "E", or read from the approved alphabet (position 14+1) = "K".
    • 2*5+0 = 10; = "F"
    • 3*5+3 = 18; = "P"
    • 4*5+4 = 24; = "X"
    • 4*5+3 = 23; = "W"
    • 4*5+1 = 21; = "T"
    • 1*5+0 =  5; = "7"
    • 1*5+4 =  9; = "D"
    • Thus the code: KFPXWT7D
  6. Or,
    • base10to25(base25to10(22344411)*5 + base25to10(40343104)) = "EAIONL59".
    • This is in a base 25 character set "0...9" and "A...N"; which equates to "KFPXWT7D" in the "23456789CDFGHJKLMNPQRTVWX" character set, swapping character for character.
  7. Note, for managers of large databases, the integer created just before final conversion to Base25, here 88076153884, is the most efficient way to store the data.
Put simply, from coordinates to OpenPostcode:
  • base10to25(base25to10(base10to5(int((55.5-53.349795)/4.2*390625))))*5 + base10to25(base25to10(int((10.75-6.260254)/5.4*390625))))) = "EAIONL59"
  • Which makes "KFPXWT7D" - swapping the base 25 "0...9, A...N" character set for "23456789CDFGHJKLMNPQRTVWX".

Calculation of Checksum

  1. For each character, multiply its number equivalent by its position (left to right); calculate the total; add the integer of the parameters west*north-wide*high (which amounts to zero in the Irish calculation and so can be ignored); and calculate the total modulus (or remainder after dividing by) the number of available checksum characters ("0123456789ACDEFGHJKLMNPQRTUVWXY" = 31) thus:
    • (14*1 + 10*2 + 18*3 + 24*4 + 23*5 + 21*6 + 5*7 + 9*8mod 31 = 5
  2. Reading from position 5+1, the checksum character is "5".
    • Thus the final 8-digit code of KFPXTV7D/5.
Put simply, to calculate the checksum for the "EAIONL59" base 25 code above:
    • (base25to10("E")*1 +base25to10("A")*2 +base25to10("I")*3 +base25to10("O")*4 +base25to10("N")*5 +base25to10(L)*6 +base25to10(5)*7 +base25to10(9)) mod 31 = 5  
    • Which equates to a checksum "5" from its character set. Thus the final 8-digit code of KFPXTV7D/5.

Conversion from OpenPostcode to Coordinates

e.g. Spire of Dublin as described by KFPX-TV7D/5.
  1. Character by character before the dash, "KFPXTV7D", translate from the base-25 character to its numerical equivalent.
    • "K" = position 15 amongst positions 0 to 24. Thus the numerical equivalent of "K" = 14, and then "F" = 10, "P" = 18, "X" = 24, "T" = 23, "V" = 21, "7" = 5, "D" = 9.
    • Then convert to two base-5 numbers, digit by digit, latitude and longitude.
    • int(14/5) = 2, 14 mod 5 = 4
    • int(10/5) = 2, 10 mod 5 = 0
    • int(18/5) = 3, 18 mod 5 = 3
    • int(24/5) = 4, 24 mod 5 = 4
    • int(23/5) = 4, 23 mod 5 = 4
    • int(21/5) = 4, 21 mod 5 = 4
    • int(5/5) = 1, 5 mod 5 = 0
    • int(9/5) = 1, 9 mod 5 = 4
    • Thus 223444115, 403431045
  2. Or,
    • Swap the character set "23456789CDFGHJKLMNPQRTVWX" for regular base 25 "0...9, A...N", which makes "EAIONL59" from "KFPXWR7D".
    • Then base10to5(base25to10("EAIONL59"))="2420334443411014"
    • Taking alternating characters x="22344411", y="40343104"
  3. The convert both to ordinary base10:
    • base10(223444115) = 199981
    • base10(403431045) = 324779
  4. Centre the point in its square:
    1. 199981+.5=199981.5
    2. 324779+.5=324779.5
  5. Return to a percentage of the maximum extent of the grid (5^8 = 390625).
    • 199981.5/390625 = 0.51195264
    • 324779.5/390625 = 0.83143552
  6. Scale up to the extent of the island boundaries (wide=5.4, high=4.2).
    1. 0.51195264*4.2 = 2.150201088
    2. 0.83143552*5.4 = 4.489751808
  7. Set on the origin of the island grid (as defined by West -10.75, North 55.5).
  8. Finally, to verify the checksum; recalculate and compare.
Put simply, from OpenPostcode to coordinates:
  • For "KFPXTV7D", swap the character set "23456789CDFGHJKLMNPQRTVWX" for regular base 25 "0...9, A...N".
    • base10to5(base25to10("EAIONL59"))="2420334443411014"
  • Taking alternating characters:
    • 55.5-(base5to10("22344411")+.5)/390625*4.2 = 53.349798912
    • (base5to10("40343104")+.5)/390625*5.4 -10.75 = -6.260248192

See also:

Subpages (1): Tools
Comments