Подтвердить что ты не робот

Абсолютная величина (абс.) NSDecimalNumber без потери точности

Мне нужно получить абсолютное значение NSDecimalNumber без потери точности. Кажется, я не могу найти способ сделать это, не превращаясь в десятичный или плавающий (с потерей точности). Есть ли способ сделать это?

4b9b3361

Ответ 1

Вы можете использовать встроенные функции класса NSDecimalNumber для сравнения числа с нолем, а затем умножить на -1, если это необходимо. Например:

- (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;
    }
}

Поскольку этот метод работает исключительно с NSDecimalNumbers, нет потери точности.

Ответ 2

В ответе есть небольшая ошибка: negativeOne должен быть указателем. Вот отредактированный ответ:

- (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;
    }
}

И вот версия, подходящая для использования в качестве категории в 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;
    }
}

Ответ 3

Если вы не хотите его умножать, нулевое вычитание значения сделает трюк.

- (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
    if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
        // negative value
        return [[NSDecimalNumber zero] decimalNumberBySubtracting:num];
    } else {
        return num;
    }
}

Ответ 4

Вариант Swift 4.0:

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
        }
    }
}

Использование

let sum = NSDecimalNumber(value: -123.33)

sum.absoluteValue()