77

Many high-level programming languages have built-in features to format a number with a system-dependent currency symbol:

-- Outputs $100.00 (en-US) or € 100,00 (de-AT)

Console.WriteLine(100.ToString("C"));  // C#
? FormatCurrency(100)                  ' VBA
...

I've been developing business software for more than 20 years, and I've not yet found a single use case for this feature.

The thing is: $ 100 is a completely different amount of money than € 100. If I store 100 in a database field and just "format the value as currency", the user will get a different amount of money depending on their system setting.

Even if I always override the locale, that does not necessarily mean that the currency symbol will stay constant: de-AT (together with a lot of other locales) switched from ATS to about 20 years ago. In that case, the amount of money displayed would not only vary by locale but also by operating system patch level.

What am I missing? For which use case is this feature actually useful?

10
  • 4
    Not to mention the fact that many countries' currency symbol is $. Mexican pesos, colombian pesos, trinidanian dollars, etc. share the same symbol $ with the US dollar. Sep 1, 2020 at 14:43
  • 2
    Note that "$100" for USD only correct for locales that put currency code in front of the value. Indeed 100 USD must be printed as "100 $" for Russia or Canada (French only text so)... But indeed you know that and just oversimplify your sample :) Sep 2, 2020 at 5:02
  • 2
    I'd like to point out that, at least for .NET, ToString and other formatting methods will fall-back to the System locale, but can be overridden an application and thread level or specified as a parameter.
    – Simon
    Sep 2, 2020 at 10:04
  • 5
    print(f'${100:f}') does not do any currency formatting. It simply prints the integer 100 as a fixed point number with the default number of 6 decimals and adds the string prefix "$" in front.
    – ruohola
    Sep 2, 2020 at 21:36
  • 2
    @ruohola: Now this is embarrassing... you are completely right, of course. Looks like Python "did it right". I have removed that example.
    – Heinzi
    Sep 3, 2020 at 8:19

7 Answers 7

35

Is there a use-case for build-in currency formatting?

Basically, with currencies you have two ways of working:

  • in a currency-aware environment, where people register amount sometimes in local and sometimes in foreign currency: you will never use the default built-in feature. Instead you’ll store a currency amount and a currency code.
  • in a currency-neutral environment. Believe it or not, most private people and most small businesses around the world work only with one local currency, which happens to be the currency configured in their OS settings and never changes. Using the build-in formatting then takes advantage of this fact, and use OS configuration instead of forcing you to add your own configuration step in your software for this. By the way, this formatting has generally also the advantage of using the right decimal and thousand separators.

So yes, there is a use-case for this feature.

But with limitations

This being said, I’m not sure that this standard feature works well and out of the box and in a portable way with:

  • currencies that are expected to be displayed with a different number of decimals than the usual two (such as JPY which are usually shown with no decimals at all, or KWD which take 3 decimals) (if you know, please comment)
  • local financial usages of showing negative amounts either with a minus, or as a positive number between brackets
  • other practical usages, such as showing the currency symbol to the left (US, UK) or to the right (FR, DE) of the amount.

Although OSes may handle these rather well (e.g.: Windows, macOS), the OS independent programming language implementations are sometimes full of surprises and missing flexibility, which could limit the use-case of this feature, but for other reasons.

21
  • 8
    "most private people and most small businesses around the world work only with one local currency" - the adoption of the Euro blew that assumption out of the water. That exact event is now receding into the past, but the possibility that a single locale will at some point change its working currency (whether through a currency union, or through revaluation) is a very real possibility to be accomodated in the design of any modern financial system.
    – Steve
    Sep 1, 2020 at 14:21
  • 19
    @Steve 40 years ago, when I was a teen, I lived on French German border. I had two boxes for my pocket money, one in FRF and one in DEM. But even in those times, most of the software dealt only with one (local) currency, and multi-currency was a rare optional feature that only SMB’s in border regions really asked for. So, believe it or not, this reality of the local currency was already there long before the euro. It has nothing to do with currency, but economic reality of most brick&mortar SMBs, which is not the reality of international finance.
    – Christophe
    Sep 1, 2020 at 14:41
  • 9
    +1 for using currency ISO codes (USD, EUR, COP, BTC, etc.) instead of symbols. Many countries' currency symbol is $. Mexican pesos, colombian pesos, trinidanian dollars, etc. share the same symbol $ with the US dollar. Sep 1, 2020 at 14:45
  • 11
    @Steve Now don’t misunderstand me: personally I work in an international financial environment and I always preferred multi-currency (already as teen, as explained above). But personally I also prefer to use an open source software developed in the US that will display currency-less amounts with a euro symbol because it uses os formatting, rather than hard-coded dollars symbol which would make it instantly useless here, if would have to print anything. And that is the use-case I was advocating: small software designed for very basic but universal needs.
    – Christophe
    Sep 1, 2020 at 14:48
  • 15
    @Christophe: I think you've misinterpreted Steve's comment. He's saying that the adoption of the Euro broke the only-ever-one-currency assumption for many users. (If you had a ledger entry representing DM 300, you wouldn't want it to suddenly claim "€ 300" the next time you updated your OS.)
    – ruakh
    Sep 1, 2020 at 21:37
13

You are absolutely right, formatting using a system-dependent currency symbol is dangerous. I actually knew people who lost lots of money through that. Especially with US dollar and Euro being close enough that the numbers make sense.

On iOS you typically use a currency code, and the currency code is displayed in a system dependent way. For example, if the currency code is “Hong Kong Dollar”, that will be displayed as “Dollar” in Hong Kong and as “Hong Kong Dollar” everywhere else. Or take the currency symbol “Euro”, which may be displayed as € or Euro, before or after the number, depending on your system.

But just marking something as “Currency” is stupid and dangerous. I think Excel does that.

1
11

The question seem to be "why programming languages, frameworks and operating systems support features that are not the best practices for professional developers in large multinational corporations"... and the answer is there are sometimes developers who are not in that category.

If your language only supports enterprise-level features you will not be able to get large adoption. This is indeed concern for languages either targeting "everyone" - like C#, Basic, Java, Python,...

Imagine a regular second day assignment "Alice had 10(units of your local currency) and payed 4 for candy, print how much she had left" - normally it requires knowledge of one basic numeric type (like int) and way to print with possibly default formatting. Now if we require proper currency handling:

  • one must understand difference between general purpose numeric types and monetary once (like float and decimal in C#)
  • must understand complex types to combine amount, currency, and potentially other property as rounding rules to represent "10 units of currency". Probably would need to understand difference between mutable/immutable types.
  • must have some understanding of globalization to know how to pick "local" currency format
  • indeed language will not support inline string literals as those are bad for localization, so some understanding of localization in given framework/language is needed too.
  • since the goal is to be really serious in proper support of localization/globalization good understanding of RTL/LTR languages and mixed strings - clearly such assignment solution must support all sorts of combinations - Hebrew string with Czech koruna for currency is a good start.

This would make writing reasonably correct code that handles money for individual person on they local machine too hard and make language not suitable for beginners and hobbyist.

One writing they first (and possibly last) piece of code to calculate savings growth based on percentage rate is unlikely to ever need that in multi-currency environment.

There are a lot of features that simply should not exist in a language/framework based on same reasoning:

  • string literals can't be used for anything but maybe filed names, should not be printable by itself. Only localizable strings should be allowed
  • Date/time must not exist by itself without explicitly specifying timezone information and rules to apply when timezone information changes
  • no naked numeric types (int, float). Every numeric value must have units of measure and directly or indirectly properties (like rounding rules, overflow rules, precision rules, compatibility with other types for all operations).
  • no "just random numbers generators" - every single one must specify distribution and randomness source at the very least.
  • all math operations must be super hardened. Integer division should only allow precise case - 2/3 should fail. Rounding must have explicit direction always specified. Operations loosing precision must define outcome explicitly inline in the code - even "+ 1" must specify that to avoid getting lost in case of large float numbers.
4
  • I think what this shows is that some of these things should either be on a school maths curriculum, or at the very least there should be professional regulation that requires coders to have studied these subjects.
    – Steve
    Sep 2, 2020 at 12:10
  • 1
    @Steve having defaults that aren't universally applicable is still useful.
    – Caleth
    Sep 3, 2020 at 10:03
  • @Caleth, I agree. But it can be crucial for a coder (and indeed users) to know that certain things are defaults, not immutable axioms.
    – Steve
    Sep 3, 2020 at 13:02
  • IMO, using a fixed currency (especially if it's displayed unambiguously) is better than using the local one, since it ensures that the value is correct, even if it isn't displayed in the user's preferred representation. (See softwareengineering.stackexchange.com/questions/415441/… for an example of how things can go wrong.) Sep 4, 2020 at 0:10
8

There are a lot of long answers to a simple question here. You ask for a use-case and there's a simple one that I don't think has been mentioned yet: games.

If a game involving money is set in an ambiguous location, why not use the players local currency? It creates a more immersive experience and, as the feature is built into the language, costs very little to add to the game.

5
  • 1
    I was about to provide this exact counterexample Sep 2, 2020 at 12:21
  • 9
    Fair enough, but given that $40,000 buys you a Mercedes, while 40000 Đồng buys a bowl of Pho, I'd say that's a rather poor attempt at improving immersion. You end up with in-game prices being laughably inadequate for some locales
    – crizzis
    Sep 2, 2020 at 20:40
  • @crizzis You're right, but having the right currency symbol can still be very valuable even if the numbers are all off. Independently of realism, the point of a currency symbol is to communicate, and immersion need not be broken by costs being wrong so long as they are internally consistent. When I was a kid growing up in Russia, there was a time while I had absolutely no idea what a "$" symbol meant, or how much a car cost. Having a recognizable currency symbol in-game would in many cases just tell people "this is money", not "this is [specific currency with contemporaneous value]".
    – mtraceur
    Sep 3, 2020 at 18:43
  • I was about to give the same answer, but I think the argument is that you wouldn't build such a feature into the OS if it was for such a niche use. There must have been more common LOB scenarios OS developers were thinking of. Sep 4, 2020 at 2:04
  • @crizzis Well, for euro and dollar numbers are comparable enough and this covers a lot of gamers and developers already. Yuan has exchange rate of ~1:8 with euro, so just imagine you stepped in a time machine transporting you to 2000 (or 2040 if a game is developed by Chinese and you play in EU). Besides, you still get some "this is money" feeling even if stuff has wacky prices (eg Japan). People mostly don't complain that food or ordinary tools in games costs few gold pieces and is therefore worth hundreds or thousands right now. (see, I didn't put any currency there :P ) Sep 4, 2020 at 9:28
7

Thirty years ago or more it was probably still reasonable to assume that most computer systems that dealt with financial amounts, did so exclusively in the local currency.

In the English-speaking world and the advanced economies more generally whom computers were built to serve, the local currencies had never changed during the computer era, and many could be traced back centuries, so the idea of a local currency changing was also a fanciful future possibility.

Both Python and VBA can trace their language design back that far. The design of Excel (as @gnasher729 mentions in his answer) goes back even further.

The .NET platform which came together in the late 90s likely inherited that design perspective without further close consideration. It does however also have the option to accept a specific culture as a parameter to the string formatting, which need not be the local culture, so there was some consideration of the potential of handling multiple currencies.

Nowadays, currencies have become as vexed as datetimes, and the only sane option is to store the currency denomination with the amount, in the same way as storing the local timezone or location with the datetime. And god help the developer who has to deal with multiple currencies within the same system, because string formatting will be the least of his concerns.

So it seems to me that the answer to the question, is that the currency formatting functionality of those languages, which bases the format on the system settings, is simply an obsolete feature, and a legacy of decades-old design.

11
  • The change to Euros in Europe happen during the computer era. Sep 1, 2020 at 14:39
  • I understand what you’re saying. But it’s not a question of modernity. Working multi-currency (not even speaking about conversion rates) requires skills, and some people out there are already stressed by monetary amounts and are really happy to use a simple software for their day to day personal finance, without adding any complexity that is not of interest for them. I’m not advocating currency- less systems. I just think there is a market for certain products where simplicity wins because in the end, what makes the fortune or the misery of a product is its users happiness ;-)
    – Christophe
    Sep 1, 2020 at 15:15
  • 9
    At the time we had a client who had quoted for a large contract in Excel, in the Netherlands, using "Currency", and they saw Dutch Guilders. The customer in Germany opened the document and saw the same numbers but marked as DM. The amount quoted looked about 20% higher than it should have been, so they had no chance to get the contract.
    – gnasher729
    Sep 1, 2020 at 22:32
  • 1
    @gnasher729, then they had the luck that both companies used the same translation in Excel. Otherwise, the end-amount of the quote would have been "Unknown formula SOM". Sep 2, 2020 at 5:39
  • 2
    The UK changed from pounds, shillings and pence to pounds and pence in 1971. This was within the computing era, more than 30 years ago, and in the English speaking world
    – Dezza
    Sep 2, 2020 at 14:49
5

TL;DR

Currency formatting has been an OS-level configuration for decades now, and the pre-internet days were a very different beast in terms of the frequency of international transactions and the need for someone in region A to express money using region B's currency.

I suspect the OS-centric currency settings are a relic of the past, kept in either because it simply hasn't been re-evaluated yet, or specifically to provide some backwards compatibility for older tools.


This not not about formatting

While some existing answers provide information and food for thought, I'm also noticing a lack of distinction being made between the choice of currency versus the choice of currency formatting.

While the formatting of currency makes sense to be a local machine decision, the currency symbol itself (not its location - which is also formatting) doesn't quite make sense to be decided by the machine instead of the data source which provided the monetary amount which needs to then be formatted.

It makes no sense for someone to tell me "It costs 100" and for me to then go "oh I prefer that those be 100 yen then!".

I agree on all of the formatting arguments making sense as local machine decisions, but not on the choice of the currency symbol itself, specifically.


What's the benefit of having the OS decide the symbol?

However, currency formatting (and all other numerical formatting) has been an OS-level configuration for decades now, and the pre-internet days were a very different beast in terms of the frequency of international transactions and the need for someone in region A to express money using region B's currency.

There's only one scenario where having this be a local machine decision makes sense:

  • If you're developing software that you intend to sell in regions with a different currency
  • If your customer's ecosystem itself only ever works in its own chosen currency, without ever changing. This could be a single machine, single customer, or a company who operates within one specific currency region.

This is the only case I can think of where this setting is not a problem and actually adds something of value.

In such a case, developers of the software don't need to explicitly account for any future customer's possible currency, in case their software sells well internationally. They wouldn't need to adjust and re-release their code just because their tool is now also being sold in another country.

Instead, they can just represent money numerically and label it as "whatever currency you (the client) uses", and then can blindly trust that the customer's machine presents this currency the way they like to see it.

When you are a customer whose entire ecoysytem (and therefore all input/output of that software) is in a single currency, then monetary values really can be represented as "just a number" to you, since you never need to distinguish between different currencies.

As a basic example, if you need to divide 100 moneys between 5 people, then each person gets 20 moneys. This is correct regardless of what currency you work with, as long as all the values I just used are expressed in the same currency.
However, if one of those people needs to be paid in USD and the others in EUR, then your elegant mathematical and currency-free calculation goes out the window.

With the advent of the internet and international transactions, the whole "single currency ecosystem" idea went straight out the door.

I suspect the OS-centric currency settings are a relic of the past, kept in either because it simply hasn't been re-evaluated yet, or specifically to provide some backwards compatibility for older tools.

5
  • I think not even your basic example is universally correct. I just learnt that a few non-decimal currencies exist even today, for example the Malagasy ariary in Madagascar, which is divided into just 5 sub units, not 100 like Euro or Dollar. If I understand correctly, this means that you cannot divide 1 ariary between 10 people, much like you could not divide 1 euro between 200 people. The type of currency therefore determines which mathematical operations are possible and which are not. Sep 3, 2020 at 5:46
  • @ChristianHackl: Even if the currency doesn't follow a decimal structure, doesn't mean that I can't express it numerically. A day is not broken in decimal parts but you still understand how much 2.5 days is, because fractionally 0.5 day = 12 hours. You could swing either way with this, either expressing the decimal part as is (.1, .2, .3, .4, .0) and simply have the backend logic account for that (note that formatting isn't something the backend depends on), or you could stick with proper decimals and do (.20, .40, .60, .80, .00). Neither of these contradicts my answer.
    – Flater
    Sep 3, 2020 at 9:28
  • I would presume the original thinking was something like "most programs only work with one hard-coded currency, or one currency which is assumed to be the current user's/system's currency. If you need to work with multiple currencies, you can store which currency it is out-of-band - incidentally, you can do this by storing the locale string and then pass that along with the number directly into the routine that formats/prints it".
    – mtraceur
    Sep 3, 2020 at 18:30
  • @mtraceur: I'm not sure how that is functionally different from my answer.
    – Flater
    Sep 3, 2020 at 22:39
  • It's different because your answer is judging it to be an overall bad design which is outdated and hasn't been reevaluated yet, while my comment shows a perspective on the design which is rather favorable and timeless - I could easily see someone using that reasoning as an argument for making or keeping this formatting API design in modern times.
    – mtraceur
    Sep 4, 2020 at 4:05
0

Handling multiple currencies has been a problem since many centuries (and even millennia). Only the early computing solutions (initially based on US English assumptions) oversimplified the problem.

Multiple currencies will not end, new currencies are still being created (notably virtual currencies, or "community/social" currencies that are being created locally to counter the bad influence of world companies on the local economy).

No unification has been made as it is not realistic for many markets. And let's remember that now all businesses are made in a worldwide context. It makes no sense today to make any business (or even social interactions) with a single currenciy.

You may think that the ISO codes are enough, but this is false, many currencies used today are not encoded just because they are not traded openly on world markets (some local currencies forbid such trades to favor the development of local businesses and activities and more social/balanced terms of exchanges in terms of actual wror or service delivered and the time/efforts spent to resolve real problems).

ISO codes are good for these currently traded currencies in a multilingual worldwide context; they are still poor to modelize the social interactions. Consider each currency to have its own identity and own value (possibly independent and not convertible to other currencies ecept by specific/ad hoc private agreements between their users).

What is important then is to identify the users or communities accepting to trade them. As we identify organizations, there can be millions. A single 3-character code will not represent all organizations of the world. And each organization adopts its own terminology, conventions and languages they understand.

In summary, currencies are not bound to any system (no social interaction) and a system-level currency does not make any sense or to the "open" world market where they "may" be traded (not always the case).

So you need a clear concept where amounts identify both the sums/values, and the identity of the currency. Formatting it is a secondary aspect which is valid only within the scope of communities accepting to trade the currency openly and not just privately (private transactions occur much more often than transactions on open traded markets: you call this the "black market", and governments don't like it, but it has always existed). The only interest of "open" currencies is that governments and banks accept to trade them in a limited market, but they also offer a limited warranty of the value (we know that these warranties are very limited, and in fact they are decreasing: "open" currencies can be seized legally by governments or banks for their own interest without asking to communities; but it is the base of the fiscal systems that governments all depend on, but government should remember that they can do that only because they have a limited trust provided by their population which have only transferred a part of their freedom for making their own trading decisions without permission).

Not all currencies are convertible, as well not all of them are translatable. The formatting options vary also a lot (not all use a decimal system, not all use the same rounding conventions). Each currency identifies its own market and a set of people with their own cultures and conventions, and a set of private transactions between them, and their own rules to govern their emissions (and let's not forget that some "world currencies" are not even tradable openly, they are reserved for some institutions, like the DTC from the World Monetary Fund, and many assets reserved to traders on very risky markets: there are tons of funds, actions, obligations, warrants constantly created, and most of them are unregulated, and most escape the fiscal systems as they are not even located in a clear juridiction; many of them are also abandoned every day and fall to a null value for any other trading, exactly like organizations are being created and die).

All currencies have a limited lifetime, just like organizations, countries, and people in real life, and just like the trust that they give to each other, or revoke at incredible rate. It is then nonsense to speak about a "system currency" unit (introduced in the 1960's but already abandonned today or that should no longer be used as it was a bad design and bad representation of the real world).

9
  • 2
    So in summary "no good reason" but you felt you needed to use 4k to say it?
    – tripleee
    Sep 1, 2020 at 17:30
  • Interesting economic thoughts. When a virtual currency makes it way through, people usually find an ISO pseudo-code even if it is not formally defined (see bitcoin. Before a currency is well recognized, there are however considerable risks about its value, and more importantly legal implications far beyond registration in an IT system (e.g. countries that forbid transactions in virtual currencies, how to value these currencies for income taxation anyway, how to account for change in value, etc...)
    – Christophe
    Sep 1, 2020 at 18:40
  • There won't be enough 3-letter ISO codes available for all currencies: many currencies don't have any code. Many currencies are only known and used in specific cultures. Many historic ones have their own subdivisions, many are not convertible in any stable way (given there's no valid market to trade them at predictable price for any kind of transaction between any pair of actors) Sep 1, 2020 at 19:21
  • So consider "currencies to be just "products" like apples and pears: an amount along without saying if it designates apples or pears, or litres of water, means nothing. it's just a number with some properties (a precision, and subdivisions that are not necessarily tradable like the full unit and without unambiguous convertibility with the full unit because of rounding rules applied in the community that sponsored the unit) Sep 1, 2020 at 19:25
  • 1
    @PhilippeVerdy Now if you switch from apples to watermelons, at a market stall where people want to buy some fruit to eat, four quarter watermelons cost a lot more than a single whole one. Because a whole watermelon is too much for most customers.
    – gnasher729
    Sep 1, 2020 at 22:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.