Search code examples
iosobjective-cnsdecimalnumber

Negate an NSDecimalNumber without losing the fractional part


I'm using this code to invert an NSDecimalNumber for easier arithmetic:

    self.thisTransaction.amount = [NSDecimalNumber decimalNumberWithString:self.amountField.text locale:NSLocale.currentLocale];

    NSLog(@"1 thisTransaction.amount is %@",self.thisTransaction.amount);

    // Inverts the transaction amount

    // This code negates the number, but chops off the part on the right side of the decimal

    self.thisTransaction.amount = [NSDecimalNumber decimalNumberWithMantissa:[self.thisTransaction.amount longLongValue] exponent:0 isNegative:YES];

    NSLog(@"2 thisTransaction.amount is %@",self.thisTransaction.amount);

Well, I thought the arithmetic would be easier, anyway. However, as revealed in the console readout below, the code negates the number, but truncates the number at the decimal point and returns a whole integer instead of a decimal:

2015-05-27 10:07:30.767 XXXXX[11835:10266658] 1 thisTransaction.amount is 25.49
2015-05-27 10:07:39.735 XXXXX[11835:10266658] 2 thisTransaction.amount is -25

I've looked at quite a few posts on SO, but they seem to go around in circles. I'd sure appreciate some guidance.

EDIT:

Pursuant to @rmaddy's suggestion below, I changed the code as follows:

    self.thisTransaction.amount = [NSDecimalNumber decimalNumberWithString:self.amountField.text locale:NSLocale.currentLocale];

    NSLog(@"1 thisTransaction.amount is %@",self.thisTransaction.amount);

    // Inverts the transaction amount

    NSDecimalNumber * invertedMultiplier = [NSDecimalNumber decimalNumberWithString:@"-1"];

    self.thisTransaction.amount = [self.thisTransaction.amount decimalNumberByMultiplyingBy:invertedMultiplier];



    NSLog(@"2 thisTransaction.amount is %@",self.thisTransaction.amount);

This seems to work fine.


Solution

  • If you want to negate an NSDecimalNumber you can simply do:

    NSDecimalNumber *originalNumber = ... // the original decimal number
    
    NSDecimalNumber *negatedNumber = [originalNumber decimalNumberByMultiplyingBy:[NSDecimalNumber numberWithInt:-1]];
    

    And for fun, here's another way:

    NSDecimalNumber *anotherNegate = [[NSDecimalNumber zero] decimalNumberBySubtracting:originalNumber];