Should I use NSDecimalNumber to deal with money?

Marcus Zarra has a pretty clear stance on this: “If you are dealing with currency at all, then you should be using NSDecimalNumber.” His article inspired me to look into NSDecimalNumber, and I’ve been very impressed with it. IEEE floating point errors when dealing with base-10 math have been irritating me for a while (1 * (0.5 – 0.4 – 0.1) = -0.00000000000000002776) and NSDecimalNumber does away with them.

NSDecimalNumber doesn’t just add another few digits of binary floating point precision, it actually does base-10 math. This gets rid of the errors like the one shown in the example above.

Now, I’m writing a symbolic math application, so my desire for 30+ decimal digit precision and no weird floating point errors might be an exception, but I think it’s worth looking at. The operations are a little more awkward than simple var = 1 + 2 style math, but they’re still manageable. If you’re worried about allocating all sorts of instances during your math operations, NSDecimal is the C struct equivalent of NSDecimalNumber and there are C functions for doing the exact same math operations with it. In my experience, these are plenty fast for all but the most demanding applications (3,344,593 additions/s, 254,017 divisions/s on a MacBook Air, 281,555 additions/s, 12,027 divisions/s on an iPhone).

As an added bonus, NSDecimalNumber’s descriptionWithLocale: method provides a string with a localized version of the number, including the correct decimal separator. The same goes in reverse for its initWithString:locale: method.

Leave a Comment