Urgent.News

What's breaking now, across thousands of outlets.

Editions

Tech

Money as a data type

Most guides open with 0.1 + 0.2 === 0.30000000000000004 and conclude "don't use floats for money." True, and not very useful. The interesting question is what you replace it with, because "use decimals" and "use integers" are different answers that fail in different places. Neither of them addresses the bug most likely to reach production: a function that cheerfully adds 500 US dollars to 500…

Money is not a simple number, but rather a number, currency, scale, and rounding policy. Using floats for money is not ideal as they can lose precision and cause unexpected results. Instead, using decimals or integers can provide more accurate calculations. However, these solutions still fall short of addressing the bug that most likely reaches production.

This bug involves adding monetary values of different currencies, resulting in an incorrect output of zero. The issue lies in the fact that money is not just a number, but also includes other factors like currency, scale, and rounding policy. If a type only carries the first factor (the number), the other three factors (currency, scale, and rounding policy) get scattered across call sites as assumptions.

Another problem arises when dealing with rounding. For example, when rounding to the nearest cent, a double may not accurately represent the desired value. In this case, the nearest double to 1.005 is 1.00499999999999989342, and multiplying by 100 gives 100.49999999999999. Rounding down gives the arithmetically correct result.

When using decimals or integers, the arithmetic complaints disappear. However, the issue of missing currency, scale policy, and rounding mode remains. To address this, it is recommended to store minor units (cents, satang, fils) as integer values in a BigInt. This ensures exactness, no rounding at rest, and no near ceiling issues.

To display monetary values, hand the integer value through a string and use the Intl.NumberFormat to render the value accurately. This way, the currency's exponent is taken into account, and the value is rendered correctly, including decimal places when necessary. Rounding can also be handled as a policy decision, with half-even (banker's rounding) being the default for many use cases.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Going freestanding

  • Go language can be compiled to C code, creating Solod subset.
  • Solod aims to provide Go-like experience with freestanding code.
  • Author ported Go's standard library to make packages freestanding.

More from Thursday 20 August →