2009-01-29 13 views

Respuesta

134

No hay realmente una mejor manera, pero realmente no deberías estar haciendo esto si puedes evitarlo. NSNumber existe como un contenedor de números escalares para que pueda almacenarlos en colecciones y pasarlos polimórficamente con otros NSObjects. Realmente no se usan para almacenar números en matemáticas reales. Si haces cálculos matemáticos sobre ellos, es mucho más lento que realizar la operación solo en los escalares, que es probablemente la razón por la cual no hay métodos de conveniencia para ello.

Por ejemplo:

NSNumber *sum = [NSNumber numberWithFloat:([one floatValue] + [two floatValue])]; 

sopla a un mínimo de 21 instrucciones sobre despacha el mensaje, y por mucho código de los métodos toman a desempacar el y Rebox los valores (probablemente unos pocos cientos) para hacer un valor de 1 instrucción de matemáticas

Así que si usted necesita para almacenar números en dicts utilizar un NSNumber, si tiene que pasar algo que podría ser un número o una cadena en una función utilizan una NSNumber, pero si lo que quieren hacer palo de matemáticas con tipos escalar c .

+1

me gustaría añadir que si necesita almacenar colecciones de números para los que tiene la intención de hacer un montón de matemáticas - ¿quizás realmente quieres una matriz de estilo C del tipo numérico correcto? –

+0

Cuando hace muchas operaciones matemáticas, quiere usar los escalares, quiere usar los objetos cuando necesita polimorfismo o tienen que caber en contenedores existentes. –

+0

El método adecuado en NSNumber es 'numberWithFloat:'; quizás esto haya cambiado desde el momento de la respuesta. – Nick

45

NSDecimalNumber (subclase de NSNumber) tiene todas las ventajas que usted está buscando:

– decimalNumberByAdding: 
– decimalNumberBySubtracting: 
– decimalNumberByMultiplyingBy: 
– decimalNumberByDividingBy: 
– decimalNumberByRaisingToPower: 

...

Si el rendimiento del equipo es de interés, a continuación, convertir a C++ gama std :: vector o me gusta.

Ahora ya nunca uso C-Arrays; es demasiado fácil colgar utilizando un índice o puntero incorrectos. Y es muy tedioso emparejar cada nuevo [] con eliminar [].

+0

¿Podrías explicar lo que quieres decir con "muy tedioso emparejar cada nuevo [] con eliminar []"? – jpswain

+0

Digámoslo de esta manera. En c, evite usar el puntero en absoluto. El objetivo de objetivo-c es poner una capa encima de C DE NUNCA tienes que preocuparte. C no es un lenguaje para ser utilizado directamente. Es algo que debe ser "manejado" primero. –

+0

Después de agregar dos 'NSDecimalNumber's, ¿cómo convertir el resultado' NSDecimalNumber' de nuevo a 'NSNumber'? (Esta pregunta se trata de agregar dos 'NSNumber's, sin agregar dos' NSDecimalNumber's.) – ohho

10

Puede utilizar

NSNumber *sum = @([first integerValue] + [second integerValue]); 

Editar: Como se observa por Ohho, este ejemplo es para la adición de hasta dos NSNumber casos que tienen valores enteros. Si desea agregar hasta dos NSNumber 's que tienen valores de punto flotante, se debe hacer lo siguiente:

NSNumber *sum = @([first floatValue] + [second floatValue]); 
+0

¿Cuál es el motivo del símbolo "@"? No estoy seguro de entender lo que hace en este contexto. –

+0

Ah. Ahora veo ... es un literal NSNumber, como se describe aquí: http://stackoverflow.com/a/11120371/35723 –

+0

Sí, @mikemeyers es el literal que envuelve primitivos como 'int' o' long' o es hermano mayor 'typedef''ed' NSInteger' en 'NSNumber' * objects *. – nemesis

0

En Swift se puede conseguir esta funcionalidad mediante el uso de la biblioteca Bolt_Swift https://github.com/williamFalcon/Bolt_Swift.

Ejemplo:

var num1 = NSNumber(integer: 20) 
    var num2 = NSNumber(integer: 25) 
    print(num1+num2) //prints 45 
2

La corriente top-voted answer va a dar lugar a difíciles de diagnosticar errores y pérdida de precisión debido al uso de flotadores. Si realiza operaciones numéricas en valores NSNumber, primero debe convertir a NSDecimalNumber y realizar operaciones con esos objetos.

Desde el documentation:

NSDecimalNumber, una subclase inmutable de NSNumber, proporciona una envoltura orientado a objetos para hacer base 10 aritmética. Una instancia puede representar cualquier número que puede ser expresado como mantisa x 10^exponente donde mantisa es un entero decimal hasta 38 dígitos de longitud, y el exponente es un número entero de -128 a través de 127.

Por lo tanto, se debe convertir sus instancias de NSNumber a NSDecimalNumbers a través del [NSNumber decimalValue], realice la aritmética que desee y vuelva a asignarla a un NSNumber cuando haya terminado.

En Objective-C:

NSDecimalNumber *a = [NSDecimalNumber decimalNumberWithDecimal:one.decimalValue] 
NSDecimalNumber *b = [NSDecimalNumber decimalNumberWithDecimal:two.decimalValue] 
NSNumber *result = [a decimalNumberByAdding:b] 

En Swift 3:

let a = NSDecimalNumber(decimal: one.decimalValue) 
let b = NSDecimalNumber(decimal: two.decimalValue) 
let result: NSNumber = a.adding(b)