To musi być łatwe, ale jak zsumować dwa NSNumber
? Jest jak:
[one floatValue] + [two floatValue]
czy istnieje lepszy sposób?
Odpowiedzi:
Nie ma lepszego sposobu, ale naprawdę nie powinieneś tego robić, jeśli możesz tego uniknąć. NSNumber
istnieje jako opakowanie dla liczb skalarnych, dzięki czemu można je przechowywać w kolekcjach i przekazywać je polimorficznie z innymi NSObjects
. Nie są tak naprawdę używane do przechowywania liczb w rzeczywistej matematyce. Jeśli wykonujesz na nich obliczenia matematyczne, jest to znacznie wolniejsze niż wykonywanie operacji na samych skalarach, dlatego prawdopodobnie nie ma na to wygodnych metod.
Na przykład:
NSNumber *sum = [NSNumber numberWithFloat:([one floatValue] + [two floatValue])];
Wydmuchuje co najmniej 21 instrukcji dotyczących wysyłek wiadomości i ile kodu zajmą metody, aby rozpakować i zmienić wartości (prawdopodobnie kilkaset), aby wykonać jedną instrukcję matematyczną.
Więc jeśli chcesz przechowywać liczby w dyktach, użyj znaku an NSNumber
, jeśli chcesz przekazać do funkcji coś, co może być liczbą lub ciągiem znaków, użyj znaku NSNumber
, ale jeśli chcesz po prostu używać matematyki trzymaj się skalarnych typów C.
NSDecimalNumber (podklasa NSNumber ) zawiera wszystkie gadżety, których szukasz:
– decimalNumberByAdding:
– decimalNumberBySubtracting:
– decimalNumberByMultiplyingBy:
– decimalNumberByDividingBy:
– decimalNumberByRaisingToPower:
...
Jeśli interesuje Cię wydajność obliczeniowa, przekonwertuj na tablicę std :: vector w C ++ lub podobną.
Teraz już nigdy nie używam C-Arrays; zbyt łatwo ulega awarii przy użyciu niewłaściwego indeksu lub wskaźnika. I bardzo żmudne parowanie każdego nowego [] z delete [].
NSDecimalNumber
s, jak przekonwertować NSDecimalNumber
wynik z powrotem na NSNumber
? (To pytanie dotyczy dodawania dwóch NSNumber
s, a nie dodawania dwóch NSDecimalNumber
.)
@interface NSDecimalNumber : NSNumber
Możesz użyć
NSNumber *sum = @([first integerValue] + [second integerValue]);
Edycja: jak zaobserwował Ohho , ten przykład służy do dodawania dwóch NSNumber
instancji, które przechowują wartości całkowite. Jeśli chcesz dodać dwa NSNumber
, które przechowują wartości zmiennoprzecinkowe, wykonaj następujące czynności:
NSNumber *sum = @([first floatValue] + [second floatValue]);
int
lub long
czy jest to wielki brat typedef
„ed NSInteger
do NSNumber
obiektów .
integerValue
obcina float
. Jak można głosować pozytywnie na tę odpowiedź?
integerValue
jeśli chcesz zachować dziesiętną część liczb?
Obecna, najczęściej wybierana odpowiedź doprowadzi do trudnych do zdiagnozowania błędów i utraty precyzji z powodu użycia pływaków. Jeśli wykonujesz operacje liczbowe na wartościach NSNumber, powinieneś najpierw przekonwertować na NSDecimalNumber i zamiast tego wykonać operacje na tych obiektach.
Z dokumentacji :
NSDecimalNumber, niezmienna podklasa NSNumber, zapewnia zorientowaną obiektowo otokę do wykonywania arytmetyki na podstawie 10. Instancja może reprezentować dowolną liczbę, którą można wyrazić jako mantysa x 10 ^ wykładnik, gdzie mantysa jest dziesiętną liczbą całkowitą o długości do 38 cyfr, a wykładnikiem jest liczbą całkowitą od –128 do 127.
Dlatego powinieneś przekonwertować swoje wystąpienia NSNumber na NSDecimalNumbers w drodze [NSNumber decimalValue]
, wykonać dowolną arytmetykę, a następnie przypisać z powrotem do NSNumber, kiedy skończysz.
W celu C:
NSDecimalNumber *a = [NSDecimalNumber decimalNumberWithDecimal:one.decimalValue]
NSDecimalNumber *b = [NSDecimalNumber decimalNumberWithDecimal:two.decimalValue]
NSNumber *result = [a decimalNumberByAdding:b]
W Swift 3:
let a = NSDecimalNumber(decimal: one.decimalValue)
let b = NSDecimalNumber(decimal: two.decimalValue)
let result: NSNumber = a.adding(b)
Dlaczego nie używać NSxEpression
?
NSNumber *x = @(4.5), *y = @(-2);
NSExpression *ex = [NSExpression expressionWithFormat:@"(%@ + %@)", x, y];
NSNumber *result = [ex expressionValueWithObject:nil context:nil];
NSLog(@"%@",result); // will print out "2.5"
Możesz również zbudować NSExpression, którego można ponownie użyć do oceny z różnymi argumentami, na przykład:
NSExpression *expr = [NSExpression expressionWithFormat: @"(X+Y)"];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", y, @"Y", nil];
NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);
Na przykład możemy zapętlić obliczenie tego samego przeanalizowanego wyrażenia, za każdym razem z inną wartością „Y”:
for (float f=20; f<30; f+=2.0) {
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", @(f), @"Y", nil];
NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);
}
W Swift możesz uzyskać tę funkcjonalność, korzystając z biblioteki Bolt_Swift https://github.com/williamFalcon/Bolt_Swift .
Przykład:
var num1 = NSNumber(integer: 20)
var num2 = NSNumber(integer: 25)
print(num1+num2) //prints 45