【发布时间】:2012-09-03 11:57:57
【问题描述】:
检查NSNumber 是否为分数的最佳方法是什么?
NumberIsFraction(@(0)); // NO;
NumberIsFraction(@(0.5)); // YES;
NumberIsFraction(@(1.0)); // NO;
在边境案件处理和表现方面“最佳”。
【问题讨论】:
标签: objective-c ios macos nsnumber
检查NSNumber 是否为分数的最佳方法是什么?
NumberIsFraction(@(0)); // NO;
NumberIsFraction(@(0.5)); // YES;
NumberIsFraction(@(1.0)); // NO;
在边境案件处理和表现方面“最佳”。
【问题讨论】:
标签: objective-c ios macos nsnumber
避免转换为具有较小域的类型:
BOOL NumberIsFraction(NSNumber *number) {
double dValue = [number doubleValue];
if (dValue < 0.0)
return (dValue != ceil(dValue));
else
return (dValue != floor(dValue));
}
【讨论】:
!=? NumberIsFraction(@(0.0f)) 会返回 YES,不是吗?
Jonathan、hpique 和 prashant 的解决方案都有相同的错误:它们涉及将 NSNumber 强制转换为固定精度类型(各种 double、long long 等),如果值为非常大NSDecimalNumber。例如,接受的答案在NSDecimalNumber(string: "1000000000000000.1") 上失败。
更正确的实现(作为扩展,在 Swift 中):
extension NSNumber {
var isFraction: Bool {
var decimal = decimalValue, decimalRounded = decimal
NSDecimalRound(&decimalRounded, &decimal, 0, .down)
return NSDecimalNumber(decimal: decimalRounded) != self
}
}
或者在 Objective-C 中,作为一个全局函数:
BOOL NumberIsFraction(NSNumber *number) {
NSDecimal rounded = number.decimalValue;
NSDecimalRound(&rounded, &rounded, 0, NSRoundDown);
return ![number isEqualToNumber:
[[NSDecimalNumber alloc] initWithDecimal:rounded]];
}
【讨论】:
我目前正在使用:
BOOL NumberIsFraction(NSNumber* number) {
return ![number isEqualToNumber:@(number.longLongValue)];
}
【讨论】:
long long 的转换过程中,非常大或非常负的整数会中断。
-(BOOL) NumberIsFraction: (NSNumber*)number
{
NSLog(@"%0.16g",number.doubleValue);
NSLog(@"%d", number.intValue);
double diff = number.doubleValue - number.intValue;
if (diff>0)
return YES;
else return NO;
}
【讨论】: