我需要获得NSDecimalNumber的绝对值而不会损失精度.我似乎无法找到一种方法来做到这一点,而无需转换为十进制或浮点数(精度损失).有没有办法做到这一点?
Tim*_*Tim 28
您可以使用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,因此不会损失精度.
答案中有一个小错误: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;
}
}
Run Code Online (Sandbox Code Playgroud)
这里有一个适合在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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不想乘以它,零减去该值就可以解决问题。
- (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
// negative value
return [[NSDecimalNumber zero] decimalNumberBySubtracting:num];
} else {
return num;
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法
let sum = NSDecimalNumber(value: -123.33)
sum.absoluteValue()
Run Code Online (Sandbox Code Playgroud)