2012-09-03 13 views
5

Jaki jest najlepszy sposób sprawdzenia, czy NSNumber jest ułamkiem?Sprawdź, czy NSNumber jest frakcją

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

"Najlepszy" pod względem obsługi i wydajności na granicy.

Odpowiedz

13

Uniknięcie konwersji typów z mniejszym domenie:

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

Myślę, że powinny to być '! ='? 'NumberIsFraction (@ (0.0f))' zwraca "TAK", prawda? – hypercrypt

+0

Ach, tak, brainfart. :) –

3

obecnie używam:

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

który będzie działał przez wiele liczb całkowitych, ale bardzo duża lub bardzo ujemne liczby całkowite ulegną zerwaniu podczas konwersji na/z '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

The rozwiązania z Jonathanem, hpique i Prashant wszystkie mają ten sam błąd : obejmują odlewanie NSNumber do typów o stałej precyzji (różne double, long long itd.), które zrywają się, jeśli ich wartość jest bardzo duża NSDecimalNumber. Na przykład zaakceptowana odpowiedź nie powiedzie się na NSDecimalNumber(string: "1000000000000000.1").

Bezpieczniejsze realizacja (jako przedłużenie w Swift):

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

    var isFraction: Bool { return !isInteger } 
} 

Albo w Objective-C, jako globalnej funkcji:

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