Floating Point Isn’t Base-10 Folks and That’s Not Encryption

Scott Stevenson recently talked about Cha-Ching. Cha-Ching is a “money manager”, or so Midnight Apps say. After Scott’s praise, I thought I’d take a look to see what all the fuss was about.

Unfortunately, it seems the Midnight Apps crew don’t quite understand the concept of floating point numbers and how they’re stored. A floating point number can not accurately store every base 10 number you can write down.

The IEEE 754 floating point standard stores single precision floating point numbers as a sign bit, an 8-bit exponent, and 23-bit mantissa. While I don’t have the time to explain floating point completely, suffice to say a simple value like $5.10 can’t be accurately represented with a binary floating point number. There’s a heap of information about floating point arithmetic in a classic paper What Every Computer Scientist Should Know About Floating-Point Arithmetic.

It seems someone brought to the attention of the Midnight Apps team this problem in a forum thread and they now say this is fixed: I’m betting (and I haven’t seen a fixed version to be sure) that all they’ve done is apply a data formatter to that text field. This just masks the problem, the transaction will still it appears be processed as a floating point value, and that’s not something one does with monetary values.

At this stage this was all I was going to write about Cha-Ching: it seemed to be an interesting application. It was probably not that exciting, but not that terrible, and written by some developers who haven’t done enough study to understand floating point numbers. Easy enough mistake to make. That was until I discovered…

The preference option for “encryption” of the database that does nothing of the sort. What it actually does is set a preference “ShouldEncryptDatabase” in NSUserDefaults and stores the password in the keychain (!!!). The data file is left in clear text in a happy happy XML document. You can edit the password Cha-Ching will require by simply modifying the keychain entry, or remove the need entirely by changing the “ShouldEncryptDatabase” flag to no.