2

The APP I'm writting must do some financial calculations, basically it's all about credits, debits and the balance. The only problem (so far) is that if I calculate 999999999.99 - 0.00 the result is 1000000000.00. Please, does anyone know why that happens? Here's my code:

NSNumber *totalCredits;
NSNumber *totalDebits;
NSNumber *balance;

self.credits = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
totalCredits = [self.credits valueForKeyPath:@"@sum.amount"];
double totalCreditsDouble = [totalCredits doubleValue];
self.creditLabel.text = [NSString stringWithFormat:@"%1.2f", totalCreditsDouble];

self.debits = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
totalDebits = [self.debits valueForKeyPath:@"@sum.amount"];
double totalDebitsDouble = [totalDebits doubleValue];
self.debitLabel.text = [NSString stringWithFormat:@"%1.2f", totalDebitsDouble];

balance = [NSNumber numberWithFloat:([totalCredits floatValue] - [totalDebits floatValue])];
double balanceDouble = [balance doubleValue];
self.balanceLabel.text = [NSString stringWithFormat:@"%1.2f", balanceDouble];

All the data is stored as Double.

Till
  • 27,559
  • 13
  • 88
  • 122
Carlos
  • 170
  • 1
  • 3
  • 11
  • 7
    Using `double` (or `float`) to store currency values is a bad idea, http://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency – Jack Nov 19 '13 at 00:00

2 Answers2

2

The C type double is generally not very well suited for financial calculations.

Foundation.framework has a good data type for that: NSDecimalNumber. NSDecimalNumber uses a decimal representation and has 36 digits of precision.

Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200
1

http://floating-point-gui.de/ is a good resource to start with. You are trying to store exact values using a datatype which cannot represent them with the accuracy or precision you need.

if the integrity of these calculations is important to you then you need to switch to storing these values in a format which accurately represents them.

In this case a simple solution might be to store all of your currencies in their smallest possible denomination (e.g. cents) as integers (assuming you don't need fractional cents and handle any division carefully and consistently).

Jonah
  • 17,918
  • 1
  • 43
  • 70