Its an application related to currency only. So, instead of handing the rounding function every time, I wish to be able to do it by default.
It is best to avoid Float
& Double
for currency applications. These types are based on binary floating point and are not precise with decimal fractions.
E.g. take 34 cents/pence/whatever in a currency where 100 of these make the dollar/pound/whatever then in you might use the decimal 0.34 to represent this, or 3/10 + 4/100 as the sum of 1/(10^n) fractions. Now binary floating-point (and fixed-point) uses sums of 1/(2^n) fractions. So 34/100 = 1/4 (25/100) + 9/100 = 1/4 + 1/16 + 275/10000 = 1/4 + 1/16 + 1/64 + ... (this sum could be finite or infinite depending on the decimal fraction)
Note that given this binary base your requirement to have two decimal places is not strictly possible, as regardless of how many binary places you limit yourself to some of your decimal factions will be imprecise.
So what is the solution? Integers (or fixed-point numbers, see below).
If you only need to support decimal currencies, i.e. those where the small unit is 1/100 of the larger one as in dollars/cents, pounds/pence) then you can simply use large enough integers and keep your amounts in the small unit. E.g store $12.34 as 1234 cents. If you need greater precision (say you're doing share prices etc.) you might store your values as some (decimal) factions of the small unit, say 1/100 of a cent. In this way all calculations use precise integer arithmetic operations. For string conversions you need to add/remove the currency point and then do integer conversions, or use remainder/division to split your stored value into its components and format each one.
If you need to support non-decimal currencies, or you need more range than storing as (some fraction of) the smaller unit will allow in your largest integer type, then you can store the large & small units as two integer values and handle carry operations between them yourself.
You can wrap the operations up as a value (struct
) type in Swift.
Some language support decimal fixed point arithmetic, or provide libraries which do, which is similar to what we've just described; there might be a library for Swift out there if you look. (See for example Python's decimal
, that link also covers the points explained above.)
If you wish to stick with available types then look at using Decimal
which is a decimal floating point type which provides 38 decimal digits of precision. It is not designed specifically for currency but you can use NSDecimalRound
to keep numbers to the required number of decimal places (and it even supports bankers rounding); to address your specific requirement to do this automatically you would have to wrap/extend and implement your own operators which combined the standard ones with rounding to the required number of places.
Hope this helps more than it confuses!