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 OpenPostcodee.g. Spire of Dublin 53.349795, -6.260254 (using coordinates as quoted in Wikipedia, Google imagery may vary from the exact location). - 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-**= 4.489746**6.260254**- 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- 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 - 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
- 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
- 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.
*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.*
## Calculation of Checksum- 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*****8**)**mod 31**= 5 - Reading from position 5+1, the checksum character is "5".
- Thus the final 8-digit code of
.**KFPXTV7D/**5
- 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 22344411
_{5}, 40343104_{5} - 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"
- The convert both to ordinary base10:
- base10(22344411
_{5}) = 199981 - base10(40343104
_{5}) = 324779 - Centre the point in its square:
- 199981+.5=199981.5
- 324779+.5=324779.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 - Scale up to the extent of the island boundaries (wide=5.4, high=4.2).
- 0.51195264
***4.2**= 2.150201088 - 0.83143552
***5.4**= 4.489751808 - Set on the origin of the island grid (as defined by West -10.75, North 55.5).
**55.5-****2.150201088 =**53.349798912- 4.489751808-10.75 = -6.260248192
- Thus the latitude and longitude:
**53.349798912, -6.260248192** - http://maps.google.ie/?q=53.349798912,-6.260248192
- Finally, to verify the checksum; recalculate and compare.
## See also: |