How to represent currency or money in C

ccurrency

TL;DR1 What is an accurate and maintainable approach for representing currency or money in C?


Background to the question:
This has been answered for a number of other languages, but I could not find a solid answer for the C language.

Note: There's plenty more similar questions for other languages, I just pulled a few for representational purposes.

All of those questions can be distilled down to "use a decimal data type" where the specific type may vary based upon the language.

There is a related question that ends up suggesting using a "fixed point" approach, but none of the answers address using a specific data type in C.

Likewise, I have looked at arbitrary precision libraries such as GMP, but it's not clear to me if this is the best approach to use or not.


Simplifying Assumptions:

  • Presume an x86 or x64 based architecture, but please call out any assumptions that would impact a RISC based architecture such as a Power chip or an Arm chip.

  • Accuracy in calculations is the primary requirement. Ease of maintenance would be the next requirement. Speed of calculations is important, but is tertiary to the other requirements.

  • Calculations need to be able to safely support operations accurate to the mill as well as supporting values ranging up to the trillions (10^9)


Differences from other questions:

As noted above, this type of question has been asked before for multiple other languages. This question is different from the other questions for a couple of reasons.

Using the accepted answer from: Why not use Double or Float to represent currency?, let's highlight the differences.

(Solution 1) A solution that works in just about any language is to use integers instead, and count cents. For instance, 1025 would be $10.25. Several languages also have built-in types to deal with money. (Solution 2) Among others, Java has the BigDecimal class, and C# has the decimal type.

Emphasis added to highlight the two suggested solutions

The first solution is essentially a variant of the "fixed point" approach. There is a problem with this solution in that the suggested range (tracking cents) is insufficient for mill based calculations and significant information will be lost on rounding.

The other solution is to use a native decimal class which is not available within C.

Likewise, the answer doesn't consider other options such as creating a struct for handling these calculations or using an arbitrary precision library. Those are understandable differences as Java doesn't have structs and why consider a 3rd party library when there is native support within the language.

This question is different from that question and other related questions because C doesn't have the same level of native type support and has language features that the other languages don't. And I haven't seen any of the other questions address the multiple ways that this could be approached in C.


The Question:
From my research, it seems that float is not an appropriate data type to use to represent currency within a C program due to floating point error.

What should I use to represent money in C, and why is that approach better than other approaches?

1 This question started in a shorter form, but feedback received indicated the need to clarify the question.

Best Answer

Never use floating point for storing currency. Floating point numbers cannot represent tenths or hundredths, only diadic rationals, i.e. numbers of the form p/q where p and q are integers and q is a power of 2. Thus, any attempt to represent cents others than 0, 25, 50, or 75 cents will require an approximation, and these approximations translate into vulnerabilities that can be exploited to make you lose money.

Instead, store integer values in cents (or whatever the smallest division of the currency is). When reading values formatted with a radix point, simply read the whole currency units and cents as separate fields, then multiply by 100 (or the appropriate power of 10) and add.