2009-07-24 16 views
6

Jestem zdezorientowany przez NSDecimalNumber i jego "zachowania". Mam NSDecimalNumber, który reprezentuje wartość dolara, powiedzmy 37,50. Chciałbym dowiedzieć się, ile razy mówi się, że 5.0 idzie na ten numer, a następnie wie, co zostało. Mogę uzyskać podział prosty i uzyskać 7,50, ale chcę 7 mod 2,50. Mógłbym przekonwertować na liczbę całkowitą, ale trzeba zapisać "centów", więc zastanawiasz się, czy istnieją pewne sztuczki w ramach?Jak uzyskać int i modulo (mod) podziału z NSDecimalNumber

Odpowiedz

1

Teoretycznie można zrobić kilka sztuczek przy użyciu metod NSDecimalNumber: decimalNumberByDividingBy:, decimalNumberByMultiplyingBy: i decimalValue. Podzielić liczby, pobrać strukturę liczb dziesiętnych, dowiedzieć się pozostałej części struktury, a następnie utworzyć nową liczbę dziesiętną z tą resztą i pomnożyć resztę przez pierwotny numer.

Najprostszym sposobem, aby to zrobić, byłoby prawdopodobnie ustalenie maksymalnej precyzji, jaką chcesz (nazwij N miejsc po przecinku dziesiętnym), pomnóż liczbę przez 10eN, po prostu pobierz wartość całkowitą i wykonaj podział i mod na tym. Ryzykujesz utratą danych, szczególnie w przypadku bardzo dużych liczb, więc sprawdź największy numer, jaki chcesz i ustal, jaki typ danych - jeśli taki - będzie dla Ciebie odpowiedni. NSNumber obsługuje unsignedLongLongValue.

4
  1. Podziel dywidendę za pomocą dzielnika, zaokrąglając w dół. To daje ci iloraz.
  2. Pomnożyć dzielnik przez iloraz.
  3. Odejmij od dywidendy. To dostarczy ci resztę.

(37,50 // 5) == 7; 7 * 5 == 35; 37,50 - 35 = 2,50.

(Uwaga:... // jest operator Pythona na integralnej podziału ja pożyczyłem ją tutaj Oczywiście, nie należy faktycznie próbować używać // do podziału w kod Objective-C)

+0

Aby zaokrąglić w dół, użyj floor() from math.h - zajmuje podwójne i zwraca double. –

+0

Jeśli używasz liczb dziesiętnych, staraj się pozostać w tym typie tak bardzo, jak to możliwe. Mianowicie, aby zaokrąglić użyj decimalNumberByRoundingAccordingToBehavior :. – Tim

+0

Lepiej, użyj 'decimalNumberByDividingBy: withBehavior:', aby wykonać podział. Wtedy nie musisz zaokrąglać osobno. –

6

Korzystanie przykład Peter Hoseys, ale z kodem iOS:

NSDecimalNumber *dividend = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:37.5] decimalValue]]; 

NSDecimalNumber *divisor = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:5.0] decimalValue]]; 

NSDecimalNumber *quotient = [dividend decimalNumberByDividingBy:divisor withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]]; 

NSDecimalNumber *subtractAmount = [quotient decimalNumberByMultiplyingBy:divisor]; 

NSDecimalNumber *remainder = [dividend decimalNumberBySubtracting:subtractAmount]; 
+0

Musisz ustawić prawy zaokrąglenie, jeśli jedna z dywidend lub dzielników jest ujemna. 'NSRoundingMode roundingMode = ((dividend.floatValue <0)^(divisor.floatValue <0))? NSRoundUp: NSRoundDown; ' – user500

5

Oto NSDecimalNumber kategoria, która również pracuje z liczb ujemnych i ujemnych dzielników:

- (BOOL)isNegative 
{ 
    return (NSOrderedDescending == [[NSDecimalNumber zero] compare:self]); 
} 

- (NSDecimalNumber *)invertedNumber 
{ 
    NSDecimalNumber *negOne = [NSDecimalNumber decimalNumberWithMantissa:1 exponent:0 isNegative:YES]; 
    return [self decimalNumberByMultiplyingBy:negOne]; 
} 

- (NSDecimalNumber *)moduloFor:(NSDecimalNumber *)divisor 
{ 
    NSRoundingMode roundingMode = ([self isNegative]^[divisor isNegative]) ? NSRoundUp : NSRoundDown; 
    NSDecimalNumberHandler *rounding = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:roundingMode 
                           scale:0 
                        raiseOnExactness:NO 
                        raiseOnOverflow:NO 
                        raiseOnUnderflow:NO 
                       raiseOnDivideByZero:NO]; 

    // divide and get the remainder 
    NSDecimalNumber *quotient = [self decimalNumberByDividingBy:divisor withBehavior:rounding]; 
    NSDecimalNumber *subtract = [quotient decimalNumberByMultiplyingBy:divisor]; 

    NSDecimalNumber *modulo = [self decimalNumberBySubtracting:subtract]; 
    if ([divisor isNegative]) { 
     return [modulo invertedNumber]; 
    } 
    return modulo; 
}