Converting units, vulgar fractions, and amateur mixology
This is another one of my “surely it can’t be that hard to…” stories (spoiler alert: yes it is). This time I’m dealing with the world of converting between different systems of measurement used for ingredients in cocktails.
I like to make tiny SaaS apps to solve my own problems, and in the hope that it helps other people with the same problem. Lately that has meant building apps to help with my hobbies, and the latest one of my hobbies to help is mixology.
A couple of years ago, after spending a couple of weeks ordering everything on the cocktail menu at a resort in the Philippines, I wanted to recapture the cocktail magic at home. Like a number of my obsessions, this led to working through a list — in this case the International Bartenders Association 77 official cocktails. Since I was going to the trouble of buying ingredients and making the drinks, I figured I would post them to Instagram as well. A couple of years later I have a well-stocked bar, and have posted over 200 cocktails.
In the last year or so, I’ve become interested in Tiki Culture — the nostalgic, pseudo-Polynesian kitsch movement that began after World War II, led by a couple of Californian bartenders. The bible of tiki cocktails is the Smuggler’s Cove book. Like many home bartenders, I’ve made a lot of the recipes in the book, and used its basic formulae as templates for improvising my own drinks. Tiki cocktails are complicated — they typically involve lots of different kinds of fruit juice, syrups, and spices, and mixing more than one variety of rum.
The “business” problem
Cocktail recipes tend to mix different units of measure. US recipes will almost always use fluid ounces, but will also use spoon measures. Recipes from elsewhere will usually have measures in centilitres or millilitres or both, and will also include spoon measurements. When I’m building a cocktail based on one or more recipes I sometimes get confused switching units, especially when I’m doubling everything, since I always make one for my wife too!
Another important part of a cocktail post on Insta is the stemware. I have a range of glasses I use, all with different capacities. The other thing I want to know is what the total volume of liquid I’m about to create is, and which stemware it will fit in. Making too much isn’t usually a problem, but serving a volume that only makes a splash in a glass does not look good.
What I want, is an app where I can build a list of ingredients and measures in any unit, see them all converted into all the other typical units, and see the total volume of liquid it all adds up to.
The units problem
I’m still building the app, so I’ll cover that in a later post, but what I want to talk about here is the unexpectedly complex world of converting between bar measurement systems and formatting the results.
When dealing with metric units, we usually use decimal fractions. E.g. the accepted, rounded conversion for one fluid ounce is 3 centilitres. This is usually written 3 cl. One and half fluid ounces converts to 4.5 cl and that’s how it is usually written. But, if we are display the measure in ounces, we usually write 1½ oz, not 1.5 oz. The same thing applies with spoon measurements, which are also used with metric measures. It would look strange to write half a teaspoon as 0.5 tsp, we expect to see ½ tsp.
Here’s an example from the app. I’ve added 4.5 cl and 1 tsp to the list, and I want to see those in their most usual conversions. There’s a lot going on here:
Vulgar fractions
It is possible to make a general method to format fractions by showing the numerator and the denominator separated by a slash, e.g. 1/2 for a half. This doesn’t look great in an app though, and it occupies more valuable horizontal real estate than it needs to. Unicode provides a limited set of characters to represent fractions, known as “vulgar fractions”. The term is apparently originates as a synonym for “common” — i.e. it’s a “common fraction”. Unicode chose to use it to describe them.
This seemed like it should be a solved problem, so I went hunting for libraries (I use node.js) to produce vulgar fractions from decimal fractions. I found a couple, but I quickly ran into problems with precision.
Precision problems
If we do standard unit conversion with a multiplier, one fluid ounce is actually 29.57 ml, not 30 ml or 3 cl. We can round it, but the problem is that there is no single rounding that works for the full range of typical bar measures. Converting the other way, 12.5 ml is 0.4166666666666667 of an ounce. The generally accepted conversion for 12.5ml is actually ⅖ of an ounce, so it needs rounded to .4, not .42 or the full floating point precision. This gets even worse when we want handle numbers greater than one (e.g. 1.5 ounces). We need to separate the integer part from the fractional part of a number. Because of the way that computers do floating point arithmetic, subtracting the full floating point precision from the integer part doesn’t yield exactly the same number as in the 12.5 ml conversion above.
The vulgar fraction libraries I found would only accept the precision of the actual fraction, not a rounded version. If I tried to do my system conversion with a standard multiplier first, then the library wouldn’t match a character.
I decided to give up on the libraries, and I settled for a conversion table of my own, and a map of Unicode vulgar fractions with a fixed 3 decimal place precision.
This means the conversions can be carried out with a multiplier from the table, and any decimal fraction can be converted to neatly formatted fractions.
Reuse doesn’t always make it go faster
I burnt a lot of time trying to bend the npm libraries I found to my use case, only to discover that it was actually quicker to “just do it myself”. That’s a good lesson, which I’ll apply next time I’m doing something similar!