检查NSNumber是否为分数

检查NSNumber是否为分数的最佳方法是什么?

 NumberIsFraction(@(0)); // NO; NumberIsFraction(@(0.5)); // YES; NumberIsFraction(@(1.0)); // NO; 

边境案件处理和绩效方面的“最佳”。

避免转换为域较小的类型:

 BOOL NumberIsFraction(NSNumber *number) { double dValue = [number doubleValue]; if (dValue < 0.0) return (dValue != ceil(dValue)); else return (dValue != floor(dValue)); } 

来自Jonathan,hpique和prashant的解决方案都有相同的错误:它们涉及将NSNumber为固定精度类型(不同的doublelong 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)]; } 
 -(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; }