Old Money
And more adventures with Python programming. One of the trickiest problems in British history is dealing with pre-decimal currency. Until 1971 British currency was a bit strange to say the least. There were 12 pence in a shilling and 20 shillings in a pound (so a pound had 240 pence). This is obviously not something that most off-the-shelf software can deal with, but doing calculations on old money is something that historians need to do quite a lot. During my PhD, when I was using Access databases, I had to decimalize amounts of money before I could do anything with them. That was awkward because some values in the pence column (I seem to remember that 4 and 8 were particularly annoying) gave a recurring fraction. To make things easier I arbitrarily rounded the pence values to the nearest multiple of 3, which meant that my figures were less exact than they could have been, but in practice I could live with it.
These days I can do better. Below are some technical details of how I approached the problem in Python (I like traaaainspotting…).
First I created a class to represent amounts of old money. Having first learnt about OOP in C++ I find Python objects a bit strange (members can’t be private! you don’t have to declare member variables in the class definition!! you can create and assign any member variables from anywhere!!!) but they work very nicely. This is the start of the class definition:
class OldMoney:
def __init__(self, ps=0, ss=0, ds=0, ex=True):
self.pounds = ps
self.shillings = ss
self.pence = ds
self.exact = ex
The first function is what isn’t called a constructor in Python. It initializes new instances of the object with the variables that I want it to have. There are integers for pounds, shillings, and pence, and a boolean field to say whether the values are exact. This is to help deal with the fact that some documents have illegible or missing bits which might obscure some of the information. Where this happens with a money value the XML tags will be present but empty to indicate that the value isn’t known. When the XML is converted to OldMoney objects in the Python script the empty tags need to be converted to 0 because trying to do calculations on null values won’t work. Therefore I need some way to tell whether a 0 represents a 0 explicitly stated in the document (in which case we can arrive at an exact total) or whether it represents an unknown figure (in which case calculations involving this figure can only give us a minimum, not an exact total).
But how do we do calculations with these objects? Fortunately Python allows classes to redefine operators, which makes it easy to add, subtract, compare etc. custom objects. The most basic step for any operations on an amount of old money is to convert it into a single number of pence. This is something that will be happening a lot, so I wrote a function to do it:
def toPence(self):
pencetotal = self.pence + (self.shillings * 12) + (self.pounds * 240)
return pencetotal
One of the many advantages of converting to pence before doing anything is that it doesn’t matter if there’s an unexpected value in one of the columns. For example, although 20 shillings made a pound, it isn’t uncommon to find shilling values higher than 20. You might find 50s written instead of £2.10s. If that’s what you find in the document you can preserve it in the XML (meaning it’s closer to the original information, and it’s less work when you’re tagging) but still do calculations on it with no problems. The above function is called by all the functions which redefine operators for the OldMoney class. For example, here is the function that redefines the + operator:
def __add__(self, r):
#convert objects into single number of pence
ltotal = self.toPence()
rtotal = r.toPence()
#create temporary object to hold result of addition
tempmoney = OldMoney()
#add total pence together
tempmoney.total = ltotal + rtotal
#find number of pounds
tempmoney.pounds = int(tempmoney.total/240)
#find number of pence left over after pounds
leftforshillings = tempmoney.total % 240
#divide remainder into shillings
tempmoney.shillings = int(leftforshillings/12)
#divide remainder into pence
tempmoney.pence = leftforshillings % 12
del tempmoney.total
return tempmoney
I also redefined -, ==, >, <, >=, and <=. You can also redefine += and -= but it looks like they just work as long as you’ve defined + and -. I also needed to write a new sum function as the built in one doesn’t work with custom objects. This takes a sequence of OldMoney objects and returns the total as an OldMoney object:
def sumOldMoney(monies):
total = OldMoney()
for x in monies:
total += x
return total
And this function takes an XML object containing pounds, shillings, and pence tags, and returns an OldMoney object. It uses a version of the xmltext() function that I mentioned the other day, but I’ve changed it since then so that it returns the text content as a string, or None if there is no text data.
def xmltoOldMoney(moneyelement):
money = OldMoney()
ltag = moneyelement.getElementsByTagName('pounds')
stag = moneyelement.getElementsByTagName('shillings')
dtag = moneyelement.getElementsByTagName('pence')
if xmltext(ltag[0]):
money.pounds = int(xmltext(ltag[0]))
else:
money.exact = False
if xmltext(stag[0]):
money.shillings = int(xmltext(stag[0]))
else:
money.exact = False
if xmltext(dtag[0]):
money.pence = int(xmltext(dtag[0]))
else:
money.exact = False
return money
If any tag is empty the exact variable is set to False to indicate that there is missing data and we will only get a minimum from calculations on this object.
Putting all this together, it was very easy to pull a lot of records out of an XML file and add up the money from each warrant. This showed that the sample of 50 warrants I’ve been working with, issued over a few days in August 1642, authorized the payment of nearly £14,000. War is expensive…

Comment by Ben Brumfield — 9:29 pm, 22 December 2007 [permanent link to this comment]
I don’t know Python, but it seems like you’d get better code re-use by creating a constructor for OldMoney that takes pence as its parameter. Move the pounds/shillings/pence stuff into that from your add method, and replace the guts of add with something like
return OldMoney(self.toPence()+r.toPence())If you want to make sure your certainty parameter gets set, pass that down too:
return OldMoney(self.toPence()+r.toPence(), self.exact && r.exact)Caveats: this is certainly not valid Python, so you may find yourself using what Java calls a static constructor method
OldMoney.fromPence(p, e=True)instead. I’m also presuming you want one inexact figure to make the total inexact as well, hence the boolean AND.Comment by Ben Brumfield — 9:46 pm, 22 December 2007 [permanent link to this comment]
One other thought: you could probably take a lesson from the concept of “significant digits” in scientific notation to attach inexact flags to each figure.
Say you’re adding 5/4/3? to 2/1/3. (I’ll use parens for grouping here.) Rather than get (7/5/6)? and assume the whole figure is inexact, you should be able to get 7/5/(6?)
When you’re summing, in this system you may get an estimate of how much your total is off by.
Though I suppose that if you really were serious about finding that out, you’d replace your boolean
exactparameter with an OldMoneyoff_byparameter that defaults to zero. So 5/4/3? could be represented asOldMoney(5, 4, 3, OldMoney(0,0,7))(7 pence since you know that your reading of 3 was correct insofar as 3 was between 0 and 9, as there was only one digit written).Assume furthermore that that off_by parameter has an
off_byaccessor that returns anOldMoneyobject.With that setup, you’d change your add method to
return OldMoney(self.toPence()+r.toPence, self.off_by+r.off_by)That could probably stand a bit of refactoring to separate the concept of exactness from Old Money. Remove the exact parameter from OldMoney and into its own ImpreciseMoney class, composed of two OldMoney variables. Add a bunch of ImpreciseMoney totals and you’ll get a figure and the amount it’s off by pretty easily.
Comment by Gavin Robinson — 12:20 pm, 23 December 2007 [permanent link to this comment]
Good ideas there. There is definitely a lot more scope for narrowing down uncertainty. This was just a first attempt, and I’m going to keep working on it to make it better. For now I’m just pleased that I’ve got something that works after only a few days of working with Python.
Comment by Gavin Robinson — 2:23 pm, 23 December 2007 [permanent link to this comment]
Another thought: maybe instead of a single int for each pounds/shillings/pence value I could use a list of ints. If it only has one element it’s an exact figure, and if it has two elements they’re the minimum and maximum. Might create more complications than it solves though, as I haven’t thought about it very carefully yet, let alone tried it. It’d still have the problem of using null where the figure is unknown and there’s no way of calculating any likely maximum.
Basically there are three possible cases, depending on what’s missing from the documents:
1. We can calculate an exact total.
2. We can calculate a minimum and a maximum.
3. We can only calculate a minimum.
All three scenarios are likely to occur and need to be dealt with. 3 seems to be the trickiest one. My original idea of setting an exact flag was really about dealing with 3 but isn’t good enough for 2. Your imprecise money object looks like the best solution to 2 but I’m not sure how it would deal with 3.
Comment by Ben Brumfield — 3:25 pm, 23 December 2007 [permanent link to this comment]
The more I think about this, the more I’m sure you need to separate the pre-decimal system logic from the uncertainty logic. Swapping integers with lists in your OldMoney class just mixes that logic up more.
Think about how simple your OldMoney class would be without any uncertainty logic (especially if you add a
fromPenceconstructor).Now think about an UncertainOldMoney class that contains (composition is the pattern here, rather than inheritance) an OldMoney figure, plus some kind of descriptor for how, precisely it’s uncertain. You can then concentrate on what that descriptor should be on its own, separate from the pounds/pence logic. Perhaps you represent the range with a pair of min/max OldMoney objects, perhaps a flag, perhaps my
offByOldMoney logic, or perhaps something that’s more representative of the text and explains which digits are illegible or missing. The point is, you can play with that separately once you encapsulate that logic.Comment by Gavin Robinson — 3:53 pm, 23 December 2007 [permanent link to this comment]
That’s a really good point. I also need to think more carefully about how to represent uncertainty in the XML. Right now money elements either have a value or no value, but I could include attributes to give minimum and maximum for missing values, and explanations of what’s missing and/or how it’s been filled in.
Comment by Gavin Robinson — 4:48 pm, 23 December 2007 [permanent link to this comment]
After some more thought, this could be the way to do it:
As you said, keep the OldMoney class purely for doing calculations on money, so it only has pounds, shillings, and pence member variables and the overloaded operators to do things with them.
Then another class which can have one of the following three members:
exact – a single OldMoney object showing the exact amount
range – a pair of OldMoney objects showing the minimum and maximum amount
min – a single OldMoney object showing the minimum amount (maximum is completely unknown in this case)
When adding two instances of this class I can check to see which member exists in each instance.
If left and right both have exact: the result is assigned to exact
If both have range, or one has range and one has exact: a minimum and maximum are calculated and assigned to range
If either has min: only a minimum is calculated and assigned to min
Whatever happens the same kind of object gets returned so we can do the same operations on it and check its accuracy. The actual calculations are handled by the OldMoney class, and this new class just decides what to do with the results.
I haven’t tried implementing this yet, but it looks good on paper.
Comment by Ben Brumfield — 7:57 pm, 23 December 2007 [permanent link to this comment]
I like the reorganization!
I don’t feel like I know enough about the textual issues you’re dealing with to comment on your specific design, I’m afraid. What is the circumstance under which
minwould be useful (scenario 3 above)?Comment by Gavin Robinson — 8:29 pm, 23 December 2007 [permanent link to this comment]
For example if the pounds column is so badly damaged that it’s impossible to tell anything about it, even how many digits there are (also in these documents arabic numerals aren’t used consistently, sometimes you get roman numerals or even amounts written in words!). In this case it’s only possible to say that the number of pounds can’t be less than 0, but the shillings and pence might still be known (or they might not). I might still want to use that figure in calculations, but the knock-on effect will be that any total derived from it will also be a minimum, with no known maximum.
Anyway, I think at this level of abstraction those 3 scenarios cover everything that could possibly happen. This is only meant to deal with certainty/uncertainty at the level of performing calculations. There’s scope for more subtle distinctions at other levels, such as in the XML or in the functions that pull data out of XML and put it into objects.
For example, an amount might be damaged but it might still be possible to supply the correct figure from another part of the document or by comparing with other documents. In that case the XML could indicate that the figure is supplied by an editor but believed to be correct. Then maybe you could set a parameter when importing the XML to say whether those editorial interventions should be treated as exact or unknown (depending on how pedantic you want to be).
Pingback by Investigations of a Dog » New Old Money — 5:02 pm, 24 December 2007 [permanent link to this comment]
[...] previous post: Old Money — [...]