2010-01-09 11 views
16

estoy llevando a cabo una serie de cálculos utilizando NSDecimal y estoy creando cada NSDecimal struct usando la siguiente técnica:¿Hay alguna manera de crear un NSDecimal sin usar NSNumber y crear objetos liberados automáticamente?

[[NSNumber numberWithFloat:kFloatConstant] decimalValue] 

estoy usando NSDecimal evitar el uso de autoreleased NSDecimalNumber objetos (si se utiliza el enfoque de NSDecimalNumber a cálculos exactos) Sin embargo, parece que el mecanismo de creación NSNumber también devuelve un NSNumber autorellenado del cual se extrae el valor decimal.

¿Hay alguna manera de crear un NSDecimal sin usar NSNumber y crear objetos liberados automáticamente?

+0

Realmente parece como 'NSDecimal' fue diseñado para las cosas con rangos de precisión específicos donde la precisión exacta es importante, como moneda, que se tienden a no querer convertir ** ao desde ** a 'float' o 'double' debido al riesgo de pérdida de precisión. ¿Podrías decirnos más sobre tu caso de uso? –

Respuesta

27

Desafortunadamente, Apple no proporciona ninguna forma fácil de poner valores en una estructura NSDecimal. La definición misma estructura se puede encontrar en la cabecera NSDecimal.h:

typedef struct { 
    signed int _exponent:8; 
    unsigned int _length:4;  // length == 0 && isNegative -> NaN 
    unsigned int _isNegative:1; 
    unsigned int _isCompact:1; 
    unsigned int _reserved:18; 
    unsigned short _mantissa[NSDecimalMaxSize]; 
} NSDecimal; 

pero no sé que me gustaría ir por ahí tratando de cómo las estructuras tienen valores de ingeniería inversa. Los guiones bajos en los campos en la estructura indican que estos son privados y están sujetos a cambios. No creo que se produzcan muchos cambios en las funciones NSDecimal de bajo nivel, pero estaría nerviosa porque las cosas se rompan en algún momento.

Dado que inicializar un NSDecimal a partir de un número de punto flotante se realiza mejor de la manera que usted describe. Sin embargo, tenga en cuenta que cada vez que use un valor de coma flotante perderá la precisión que ganó al usar un NSDecimal y se someterá a errores de coma flotante.

Siempre trabajo solo con NSDecimales dentro de mis cálculos de alta precisión, y tomo y exporto NSStrings para intercambiar estos valores con el mundo exterior. Para crear un NSDecimal basado en un NSString, se puede utilizar el enfoque que tomamos en el Core Plot framework:

NSDecimal CPDecimalFromString(NSString *stringRepresentation) 
{ 
    NSDecimal result; 
    NSScanner *theScanner = [[NSScanner alloc] initWithString:stringRepresentation]; 
    [theScanner scanDecimal:&result]; 
    [theScanner release]; 

    return result; 
} 

El uso de un NSScanner en lugar de NSDecimalNumber -initWithString:locale: es aproximadamente un 90% más rápido en mis puntos de referencia.

+0

La clase NSDecimal es tan incomprendida y es porque es muy intuitiva. ¿Por qué Apple lo hizo tan poco amigable con los programadores? ¿Cuáles son las alternativas a NSDecimal? –

+3

@AndrewS - Por un lado, NSDecimal no es una clase, sino una estructura, por lo que debe manejarse de forma un poco diferente que sus objetos estándar. La complejidad en las funciones de manejo NSDecimal parece provenir del deseo de hacerlas lo más rápido posible. Tenga en cuenta que pasan por referencia a estas funciones, como una sola optimización. Sin embargo, no hay excusa para no tener un constructor fácil para NSDecimales. –

+0

¿Hay un decimal más primitivo como NSInteger? –

2

Para responder a la “sin objetos autoreleased” parte, simplemente:

NSDecimalNumber *intermediateNumber = [[NSDecimalNumber alloc] initWithFloat:kFloatConstant]; 
NSDecimal decimal = [intermediateNumber decimalValue]; 
[intermediateNumber release]; 
+0

El problema aquí no es tanto que el objeto se libere automáticamente, sino que se evite asignarlo para empezar. Cualquier asignación de un NSDecimalNumber, liberado automáticamente o no, será más lento que tratar con una estructura NSDecimal: http://stackoverflow.com/questions/1704504/what-is-the-right-choice-between-nsdecimal-nsdecimalnumber-cfnumber/ 1710277 # 1710277. Hay una sobrecarga significativa en la creación y destrucción de estos objetos. También está asumiendo que están comenzando con un valor flotante, que con suerte no sería el caso cuando se trata de NSDecimals y NSDecimalNumbers. –

+0

Además, probablemente no desee utilizar -initWithFloat: por las razones que se describen aquí: http://stackoverflow.com/a/5304993/19679 –

+0

@BradLarson Es por eso que prefigé la respuesta con "To the the answer" sin autorrelleno parte de los objetos ". –

Cuestiones relacionadas