2012-09-03 15 views
5

NSNumberが小数であるかどうかを調べる最良の方法は何ですか?NSNumberが小数であることを確認してください

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

ボーダーケースの処理とパフォーマンスに関して「ベスト」です。小さいドメインを持つ型への変換を回避

BOOL NumberIsFraction(NSNumber* number) { 
    return ![number isEqualToNumber:@(number.longLongValue)]; 
} 

答えて

13

+0

私はそれらが '!='であるべきだと思いますか? 'NumberIsFraction(@(0.0f))'は 'YES'を返すでしょうか? – hypercrypt

+0

ああ、はい、brainfart。 :) –

3

私は現在使用しているジョナサン、hpiqueから

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

が、非常に大きなまたは非常に負の整数は、「long long」への変換中に/から変換されます。 –

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

ソリューションを、そして全てが同じバグを持っているのPrashant :固定精度型(さまざまにはdouble,long longなど)にNSNumberをキャスティングします。値が非常に大きい場合は破損しますNSDecimalNumber。たとえば、受け入れられた応答はNSDecimalNumber(string: "1000000000000000.1")で失敗します。

(スウィフトで拡張、など)より安全な実装:

extension NSNumber { 
    var isInteger: Bool { 
     var rounded = decimalValue 
     NSDecimalRound(&rounded, &rounded, 0, NSRoundingMode.RoundDown) 
     return NSDecimalNumber(decimal: rounded) == self 
    } 

    var isFraction: Bool { return !isInteger } 
} 

またはグローバル関数としてのObjective-C、中:多くの整数のために動作します

BOOL NumberIsFraction(NSNumber *number) { 
    NSDecimal rounded = number.decimalValue; 
    NSDecimalRound(&rounded, &rounded, 0, NSRoundDown); 
    return ![number isEqualToNumber: 
     [[NSDecimalNumber alloc] initWithDecimal:rounded]]; 
} 
関連する問題