Skip to content

Instantly share code, notes, and snippets.

@rgs
Last active March 20, 2024 19:55
Star You must be signed in to star a gist
Save rgs/6509585 to your computer and use it in GitHub Desktop.

Falsehoods programmers believe about prices

  1. You can store a price in a floating point variable.
  2. All currencies are subdivided in 1/100th units (like US dollar/cents, euro/eurocents etc.).
  3. All currencies are subdivided in decimal units (like dinar/fils)
  4. All currencies currently in circulation are subdivided in decimal units. (to exclude shillings, pennies) (counter-example: MGA)
  5. All currencies are subdivided. (counter-examples: KRW, COP, JPY... Or subdivisions can be deprecated.)
  6. Prices can't have more precision than the smaller sub-unit of the currency. (e.g. gas prices)
  7. For any currency you can have a price of 1. (ZWL)
  8. Every country has its own currency. (EUR is the best example, but also Franc CFA, etc.)
  9. No country uses another's country official currency as its official currency. (many countries use USD: Ecuador, Micronesia...)
  10. Countries have only one currency.
  11. Countries have only one currency currently in circulation. (Panama officially uses both PAB and USD)
  12. I'll only deal with currencies currently in circulation anyway.
  13. All currencies have an ISO 4217 3-letter code. (The Transnistrian ruble has none, for example)
  14. All currencies have a different name. (French franc, "nouveau franc")
  15. You always put the currency symbol after the price.
  16. You always put the currency symbol before the price.
  17. You always put the currency symbol either after, or before the price, never in the middle.
  18. There's only one currency symbol for any currency. (元, 角, 分 are increasing units of the Chinese renminbi.)
  19. For a given currency, you always, but always, put the symbol in the same place.
  20. OK. But if you only use the ISO 4217 currency codes, you always put it before the price. (Hint: it depends on the language.)
  21. Before the price means on the left. (ILS)
  22. You can always use a dot (or a comma, etc.) as a decimal separator.
  23. You can always use a space (or a dot, or a comma, etc.) as a thousands separator.
  24. You separate big prices by grouping numbers in triplets (thousands). (One writes ¥1 0000)
  25. Prices at a single company will never range from five digits before the decimal to five digits after.
  26. Prices contains only digits and punctuation. (Germans can write 12,- €)
  27. A price can be at most 10^N for some value of N.
  28. Given two currencies, there is only one exchange rate between them at any given point in time.
  29. Given two currencies, there is at least one exchange rate between them at any given point in time. (restriction on export of MAD, ARS, CNY, for example)
  30. And the final one: a standalone $ character is always pronounced dollar. (It's also the peso sign.)
@ashb
Copy link

ashb commented Sep 10, 2013

It would be useful if you could provide counter examples to say why these are incorrect assumptions.

@garu
Copy link

garu commented Sep 10, 2013

Nice compilation! "$" was also the escudo sign before the Euro, and in portuguese we call it "cifrão" when it is standalone.

Copy link

ghost commented Sep 10, 2013

ashb: Yes, that'd be good. E.g., #17: "the Cape Verdean escudo, like the former Portuguese escudo and French franc, placed its sign in the decimal position (i.e., 20$00)" from http://en.wikipedia.org/wiki/Currency_symbol

@jleader
Copy link

jleader commented Sep 10, 2013

Wikipedia claims your list of Chinese currency symbols in #18 is in decreasing order.

Also, if you want to follow the style of the names and times falsehood lists, you could split #18:

  1. There's only one currency symbol for any currency. ($ and ¢ for dollars and cents.)
  2. OK, then, there are at most two currency symbols for any currency. (元, 角, 分 are decreasing units of the Chinese renminbi.)

Also, maybe before #18:

X. A currency symbol (as distinct from a 3-letter currency code) is always a single character. (Rp for Indonesian rupiah.)

@rgs
Copy link
Author

rgs commented Sep 10, 2013

@jleader: good points. I note that the IDR isn't strong enough to buy a Unicode codepoint, like most other currencies...:)
Same remark to @garu, the cifrão is originally written with 2 bars (while the dollar has only one), but it has no separate Unicode codepoint. It is, however, much older than the US dollar, and it's its origin.

@waprile
Copy link

waprile commented Feb 28, 2014

number 31: All countries use their own currency. (Zimbabwe)

On Transnistria, it is a bit tricky. The country is officially recognized by very few other countries. http://en.wikipedia.org/wiki/International_recognition_of_Transnistria

@MartinThoma
Copy link

Could somebody explain 3 and give a counter example?

@newtrat
Copy link

newtrat commented Sep 11, 2018

@MartinThoma The example used in #4 also works for #3, since #4 is a more specific version of #3. The Wikipedia page for MGA lists denominations like 1/5 and 2/5, so presumably you'd talk about 1 1/5 ariary rather than 1.2 ariary. But the website of Madagascar's central bank does list these coins in a decimal format, as ARIARY 0,4 and ARIARY 0,2, so maybe Madagascar has switched to a decimal format since this Gist was written? I don't know how the currency is actually used in practice.

@jrbasso
Copy link

jrbasso commented Sep 27, 2018

You can add another entry saying the symbol is not always one character like USD ($)/EUR(). Some currencies use multiple like R$ and others that are even longer.

@calvinmetcalf
Copy link

Prices can't have more precision than the smaller sub-unit of the currency. (e.g. gas prices)

strictly speaking gas prices are not an example of this since the dollar is not only divided into cents but also divided into dimes (1/10 of a dollar) and mils (1/1000 of a dollar) so gas prices are just denominated in mils, their smaller sub unit.

This is also why the dime just says 'one dime' instead of 'ten cents'.

@calvinmetcalf
Copy link

@MartinThoma that one is explicitly about pre-decimal British pounds where were divided into 20 shillings each of which was divided into 12 pennies.

@eldering
Copy link

Prices can't have more precision than the smaller sub-unit of the currency. (e.g. gas prices)

strictly speaking gas prices are not an example of this since the dollar is not only divided into cents but also divided into dimes (1/10 of a dollar) and mils (1/1000 of a dollar) so gas prices are just denominated in mils, their smaller sub unit.

This is also why the dime just says 'one dime' instead of 'ten cents'.

They are an example, because the euro is only subdivided in cents, and prices are often listed to 3 decimals.

@eiennohito
Copy link

About yen and triplets: large sums are actually are written in triplets, not in fours as it can be expected from the actual number system. It is sure confusing, but that is the life.

@evcross
Copy link

evcross commented Aug 1, 2019

Prices can't have more precision than the smaller sub-unit of the currency. (e.g. gas prices)

strictly speaking gas prices are not an example of this since the dollar is not only divided into cents but also divided into dimes (1/10 of a dollar) and mils (1/1000 of a dollar) so gas prices are just denominated in mils, their smaller sub unit.
This is also why the dime just says 'one dime' instead of 'ten cents'.

They are an example, because the euro is only subdivided in cents, and prices are often listed to 3 decimals.

This one is particularly interesting to me as I work in the commodities IT space.

I'm not aware of a case where a decimal number isn't the ideal method to store an amount or price. You may want to do formatting ("1 Pound and 13 Shillings") but that's not a reason not to use decimals. You just have problems if you pick that decimal to represent Pounds or Shillings (which has further subdivisions).

I would also argue that a floating point number can be a necessary evil for storing prices. It is common in quant circles to use finite differences methods to produce important metrics. When you are doing these types of numerical methods, you want as much precision and speed as possible - a double makes the most sense.

One anecdote I have that is related: An application I worked with used a configurable field handling currencies and payments to indicate the number of decimal places to round to when determining prices. They used -1 to encode "no rounding". Turns out it is not uncommon to round to the nearest 10 or 100 yen in certain markets dealing with JPY. They had to make some pretty costly changes to unwind a nearly universal interpretation of "-1 decimal places of rounding" in the app.

@HenkPoley
Copy link

HenkPoley commented Oct 7, 2019

Another point. In the Chinese language(s) they have separate characters (besides 0 to 9 and Chinese 零 to 十) for writing financial numbers that are more resistant to malicious editing after writing/printing (think adding a longer dash to 1 to make it a 7). Meaning they have 3 ways of writing the same number, for which 2 are preferred for financial numbers.

https://en.wikipedia.org/wiki/Chinese_numerals#Standard_numbers

@majerv
Copy link

majerv commented Dec 4, 2019

Cool, I like it! :)

@omnistegan
Copy link

How about IDR, which has a subunit, but it's not generally used or displayed. (due to it's very low value)
This recently bit me when I was working on an integration. All of the third-party APIs I was interacting with required passing integer amounts of subunits.
This would be fine, except that some third-parties considered IDR to have a subunit, and some considered it to not have a subunit.
(the ISO standard is to treat it as a currency with a subunut, but some software doesn't care about standard)

In the end, I ended up juggling a different representation of IDR in my api integreation for a particular third-party and had to handle conversions to and from.

So maybe the bullet points would be:

  • If a currency has a subunit, the subunits should be displayed.
  • A currency either has subunits or it does not. (e.g. IDR)

@chrisdone
Copy link

chrisdone commented Jan 16, 2020

How about: "Any valid money in a currency can be withdrawn from the bank in cash". Counterexample: CHF is subdivided into 100, but the smallest coin is 5.

@Fryie
Copy link

Fryie commented Sep 8, 2020

After reading this list I was wondering what the best way would be to model currencies in general while respecting all these specifics.

It seems to me that prices in any given currency should always form a vector space: Obviously we can add and subtract prices. But we should also be able to multiply them by e.g. tax rates, discounts etc. So I think requiring those two operations to be always implemented for any given currency (and you may be able to reuse some code for currencies that share similar features), you should be able to write generic price calculation code for any past, present or future currency.

But maybe I'm missing something.

@shalvah
Copy link

shalvah commented Sep 23, 2020

After reading this list I was wondering what the best way would be to model currencies in general while respecting all these specifics.

You can't. In the real world, you try your best, but you often have to pick the assumptions you can live with. And not just in currencies. Languages, names, dates, addresses, ages... Trying to account for every single scenario is a recipe for madness.

@kipcole9
Copy link

After reading this list I was wondering what the best way would be to model currencies in general while respecting all these specifics.

The Common Locale Data Repository (CLDR) does a pretty thorough job of describing currencies and their decimal digits, output formatting, parsing, rounding (cash and accounting) and symbols in a localised fashion.

See number and currency formats, currency symbols and currency format localisation.

@heiglandreas
Copy link

About yen and triplets: large sums are actually are written in triplets, not in fours as it can be expected from the actual number system. It is sure confusing, but that is the life.

Large numbers (and therefore also prices) are written in pairs followed by a single triplet on the Indian subcontinent like this: 10,00,00,000 (https://en.wikipedia.org/wiki/Indian_numbering_system)

@mikaoelitiana
Copy link

@MartinThoma The example used in #4 also works for #3, since #4 is a more specific version of #3. The Wikipedia page for MGA lists denominations like 1/5 and 2/5, so presumably you'd talk about 1 1/5 ariary rather than 1.2 ariary. But the website of Madagascar's central bank does list these coins in a decimal format, as ARIARY 0,4 and ARIARY 0,2, so maybe Madagascar has switched to a decimal format since this Gist was written? I don't know how the currency is actually used in practice.

Hi @MartinThoma @newtrat,

To give more context about this, it's not that MGA is not subdivided to decimals by definition, but "de facto", we have always avoided them.
First, our smallest used coin is 10 Ariary so it's almost impossible to use decimals in real life. Also a large number of the remote population have not been to school and using decimals makes life really hard for them.
On the other hand, with the raise of mobile banking and "electronic" money, we tend to use more and more decimals for online purchases and rate conversions with other currencies.

@dtremit
Copy link

dtremit commented Feb 3, 2023

A falsehood parallel to #10 and #11 might be “all transactions are conducted in a single currency.” In Cambodia USD is widely circulated, but only in bills — change of less than $1 is returned in KHR. So e.g. if one purchases something costing 5.75USD with a 10USD note, the change given might well be 4USD + 1,000KHR.

@stephenwilcoxon
Copy link

I'm curious if anyone knows the counter-example for #17 (never in the middle)? That's the only one I haven't run into.

@shalvah
Copy link

shalvah commented Sep 19, 2023

@stephenwilcoxon Found on Wikipedia: the Cape Verdean escudo and the defunct Portuguese escudo. Also, the defunct French franc, as reported in this Stack Exchange answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment