Absolute Value (abs) of NSDecimalNumber without loss of precision

前端 未结 4 1301
情书的邮戳
情书的邮戳 2020-12-31 00:35

I need to get the absolute value of an NSDecimalNumber without loss of precision. I can\'t seem to find a way to do this without converting to decimal or float (with a loss

相关标签:
4条回答
  • 2020-12-31 01:10

    You can use the built-in functions of the NSDecimalNumber class to compare the number to zero, then multiply by -1 as appropriate. For example:

    - (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
        if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
            // Number is negative. Multiply by -1
            NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
                                                                              exponent:0
                                                                            isNegative:YES];
            return [num decimalNumberByMultiplyingBy:negativeOne];
        } else {
            return num;
        }
    }

    Since this method works solely with NSDecimalNumbers, there's no loss of precision.

    0 讨论(0)
  • 2020-12-31 01:11

    There is a minor error in the answer: negativeOne should be a pointer. Here is a revised answer:

    - (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
        if [myNumber compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
            // Number is negative. Multiply by -1
            NSDecimalNumber *negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
                                                                        exponent:0
                                                                      isNegative:YES];
            return [num decimalNumberByMultiplyingBy:negativeOne];
        } else {
            return num;
        }
    }
    

    And here is a version suitable to be used as a category on NSDecimalNumber:

    - (NSDecimalNumber *)abs {
        if ([self compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
            // Number is negative. Multiply by -1
            NSDecimalNumber *negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
                                                                             exponent:0
                                                                           isNegative:YES];
            return [self decimalNumberByMultiplyingBy:negativeOne];
        } else {
            return self;
        }
    }
    
    0 讨论(0)
  • 2020-12-31 01:16

    If you do not want to multiply it, zero subtracting the value will do the trick.

    - (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
        if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
            // negative value
            return [[NSDecimalNumber zero] decimalNumberBySubtracting:num];
        } else {
            return num;
        }
    }
    
    0 讨论(0)
  • 2020-12-31 01:29

    Swift 4.0 variant:

    extension NSDecimalNumber {
        func absoluteValue() -> NSDecimalNumber {
            if self.compare(NSDecimalNumber.zero) == .orderedAscending {
                let negativeValue = NSDecimalNumber(mantissa: 1, exponent: 0, isNegative: true)
                return self.multiplying(by: negativeValue)
            } else {
                return self
            }
        }
    }
    

    usage

    let sum = NSDecimalNumber(value: -123.33)
    
    sum.absoluteValue()
    
    0 讨论(0)
提交回复
热议问题