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 ?
Réponses
Trop de publicités?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.
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;
}
}
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;
}
}
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()