2011-07-15 24 views
14

Estoy manejando enteros grandes sin signo de 64 bits de una fuente JSON que están siendo analizados en NSDecimalNumbers, que aparentemente es "representar fielmente números de precisión arbitraria".NSDecimalNumber y enteros largos largos sin firmar (64 bits)

El problema que tengo es que no puedo obtener los números correctos de esta clase. Por ejemplo (utilizando el valor más grande posible):

print (unsigned long long) [[NSDecimalNumber decimalNumberWithString:@"18446744073709551615"] unsignedLongLongValue] 
= 0 // Incorrect 
print (unsigned long long) [[NSDecimalNumber decimalNumberWithString:@"9223372036854775808"] unsignedLongLongValue] 
= 9223372036854775808 // Correct 
print (unsigned long long) [[NSDecimalNumber decimalNumberWithString:@"9223372036854775810"] unsignedLongLongValue] 
= 9223372036854775808 // Incorrect 

Parece que no puedo conseguir algo más grande que el máximo firmado mucho, mucho valor a partir de un NSDecimalNumber. No es el gusto valores mayores que 9223372036854775808. Sin embargo, parece que el número se almacena en la precisión completo dentro de un NSDecimalNumber, como:

po [[NSDecimalNumber decimalNumberWithString:@"18446744073709551615"] stringValue] 
= 18446744073709551615 

me he dado cuenta de que los objetos NSNumber pueden manejar las obras de estos grandes números finos y unsignedLongLongValue correctamente. Son solo NSDecimalNumbers (con los que estoy atascado) que no funcionan.

¿Cómo puedo obtener valores largos correctos sin firmar de NSDecimalNumbers? O al menos conviértalos en objetos NSNumber donde unsignedLongLongValue funciona.

Respuesta

11

que he tenido una respuesta de Apple en este tema a través de los foros de desarrolladores:

Ésta es una cuestión de la legitimación con NSDecimalNumber donde los simples descriptores de acceso (por ejemplo, [firmado] longLongValue) pasan por el doubleValue acceso - este valor que requiera más de 53 bits de precisión se redondeará de forma inapropiada. No dude en informar de un error acerca de este tema y mencionar fallo número 8220543.

Dicho esto, si son sólo conseguir números de 64 bits de JSON, usted debería ser capaz de usar sólo NSNumber en lugar de NSDecimalNumber.

Así que estoy resolverlo cambiando analizador de SBJson a JSONKit, que no sólo es mucho más rápido, sino que también asigna los números en objetos NSNumber en lugar de objetos NSDecimalNumber.

+1

Me pregunto si el problema persiste en el IOS de 5 NSJSONSerialization clase? – adib

+0

No era consciente de esto en iOS 5, lo comprobaré, ¡gracias! –

+0

¡Persiste totalmente en la NSJSONSerialización de iOS 5! o_O –

6

Si aún desea extraer un valor de tiempo largo sin signo de un NSDecimalNumber, se puede utilizar el enfoque sugerido por Johne here y hacer algo como lo siguiente:

NSDecimalNumber *testNumber = [NSDecimalNumber decimalNumberWithString:@"18446744073709551615"]; 
unsigned long long ullvalue = strtoull([[testNumber stringValue] UTF8String], NULL, 0); 
NSLog(@"Number:%llu", ullvalue); 

que produce el resultado correcto de

Número: 18446744073709551615

traté de hacer esto utilizando un NSScanner:

NSScanner *theScanner = [[NSScanner alloc] initWithString:[testNumber stringValue]]; 
unsigned long long outputValue; 

[theScanner scanLongLong:(long long *)&outputValue]; 
[theScanner release]; 

pero, por desgracia, sólo lee los valores de tiempo largos firmados, por lo que la anterior muestra el valor incorrecto de 9223372036854775807.

+0

Gracias por esa sugerencia, ¡buena idea si estás atrapado con NSDecimalNumbers! –