Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to store currency values in C++

Tags:

c++

currency

People also ask

Which data type is best for currency amounts?

The best datatype to use for currency in C# is decimal. The decimal type is a 128-bit data type suitable for financial and monetary calculations. The decimal type can represent values ranging from 1.0 * 10^-28 to approximately 7.9 * 10^28 with 28-29 significant digits.

Should you use float for money?

Float & Double are bad for financial (even for military use) world, never use them for monetary calculations. If precision is one of your requirements, use BigDecimal instead.

How do you store money in a database?

The first important rule is, always store values as fractional units. It can be tempting to store a value such as $10 as 10.00 in your database. However, storing monetary values with a decimal point can cause a lot of issues. Instead, you should always store monetary values in their minor unit form.

What would be a good data types to store prices for an international shopping website?

The best type for price column should be DECIMAL. The type DECIMAL stores the value precisely. For Example - DECIMAL(10,2) can be used to store price value. It means the total digit will be 10 and two digits will be after decimal point.


Don't store it just as cents, since you'll accumulate errors when multiplying for taxes and interest pretty quickly. At the very least, keep an extra two significant digits: $12.45 would be stored as 124,500. If you keep it in a signed 32 bit integer, you'll have $200,000 to work with (positive or negative). If you need bigger numbers or more precision, a signed 64 bit integer will likely give you all the space you'll need for a long time.

It might be of some help to wrap this value in a class, to give you one place for creating these values, doing arithmetic on them, and formatting them for display. This would also give you a central place to carry around which currency it being stored (USD, CAD, EURO, etc).


Having dealt with this in actual financial systems, I can tell you you probably want to use a number with at least 6 decimal places of precision (assuming USD). Hopefully since you're talking about currency values you won't go way out of whack here. There are proposals for adding decimal types to C++, but I don't know of any that are actually out there yet.

The best native C++ type to use here would be long double.

The problem with other approaches that simply use an int is that you have to store more than just your cents. Often financial transactions are multiplied by non-integer values and that's going to get you in trouble since $100.25 translated to 10025 * 0.000123523 (e.g. APR) is going cause problems. You're going to eventually end up in floating point land and the conversions are going to cost you a lot.

Now the problem doesn't happen in most simple situations. I'll give you a precise example:

Given several thousand currency values, if you multiply each by a percentage and then add them up, you will end up with a different number than if you had multiplied the total by that percentage if you do not keep enough decimal places. Now this might work in some situations, but you'll often be several pennies off pretty quickly. In my general experience making sure you keep a precision of up to 6 decimal places (making sure that the remaining precision is available for the whole number part).

Also understand that it doesn't matter what type you store it with if you do math in a less precise fashion. If your math is being done in single precision land, then it doesn't matter if you're storing it in double precision. Your precision will be correct to the least precise calculation.


Now that said, if you do no math other than simple addition or subtraction and then store the number then you'll be fine, but as soon as anything more complex than that shows up, you're going to be in trouble.


Look in to the relatively recent Intelr Decimal Floating-Point Math Library. It's specifically for finance applications and implements some of the new standards for binary floating point arithmetic (IEEE 754r).


The biggest issue is rounding itself!

19% of 42,50 € = 8,075 €. Due to the German rules for rounding this is 8,08 €. The problem is, that (at least on my machine) 8,075 can't be represented as double. Even if I change the variable in the debugger to this value, I end up with 8,0749999....

And this is where my rounding function (and any other on floating point logic that I can think of) fails, since it produces 8,07 €. The significant digit is 4 and so the value is rounded down. And that is plain wrong and you can't do anything about it unless you avoid using floating point values wherever possible.

It works great if you represent 42,50 € as Integer 42500000.

42500000 * 19 / 100 = 8075000. Now you can apply the rounding rule above 8080000. This can easily be transformed to a currency value for display reasons. 8,08 €.

But I would always wrap that up in a class.


I would suggest that you keep a variable for the number of cents instead of dollars. That should remove the rounding errors. Displaying it in the standards dollars/cents format should be a view concern.