21 votes

Valeur absolue (abs) de NSDecimalNumber sans perte de précision

J'ai besoin d'obtenir la valeur absolue d'un NSDecimalNumber sans perte de précision. Je n'arrive pas à trouver un moyen de le faire sans convertir en décimal ou en flottant (avec une perte de précision). Existe-t-il une méthode pour y parvenir ?

28voto

Tim Points 33042

Vous pouvez utiliser les fonctions intégrées de la classe NSDecimalNumber pour comparer le nombre à zéro, puis le multiplier par -1, le cas échéant. Par exemple :

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

Comme cette méthode fonctionne uniquement avec les NSDecimalNumbers, il n'y a aucune perte de précision.

9voto

mts Points 380

Il y a une erreur mineure dans la réponse : negativeOne devrait être un pointeur. Voici une réponse révisée :

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

Et voici une version adaptée pour être utilisée comme catégorie sur 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;
    }
}

6voto

Carolyn Points 103

Si vous ne voulez pas le multiplier, la soustraction zéro de la valeur fera l'affaire.

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

5voto

pchelnikov Points 21

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

utilisation

let sum = NSDecimalNumber(value: -123.33)

sum.absoluteValue()

2voto

pawello2222 Points 16

Swift 5

Vous pouvez utiliser le magnitude propriété de Decimal :

extension NSDecimalNumber {
    var absValue: Self {
        .init(decimal: decimalValue.magnitude)
    }
}

let number = NSDecimalNumber(string: "-123.456")
let absNumber = number.absValue // 123.456

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X