2012-01-05 8 views
6
NSLog(@"%llu\n\n", ULONG_LONG_MAX); 

NSDecimalNumber *decimal = [NSDecimalNumber decimalNumberWithString:@"154550038129946620"]; 
NSLog(@"%@", decimal); 
NSLog(@"%llu\n\n", [decimal unsignedLongLongValue]); 

decimal = [NSDecimalNumber decimalNumberWithString:@"154550038129946628"]; 
NSLog(@"%@", decimal); 
NSLog(@"%llu", [decimal unsignedLongLongValue]); 

Ambos valores son inferiores a ULONG_LONG_MAX. Pero, lo que vemos en la salida es:Objetivo C extraña conversión decimal a larga larga

2012-01-05 17:41:55.879 test[1276:207] 18446744073709551615 

2012-01-05 17:41:55.969 test[1276:207] 154550038129946620 
2012-01-05 17:41:56.095 test[1276:207] 154550038129946624 

2012-01-05 17:41:56.096 test[1276:207] 154550038129946628 
2012-01-05 17:41:56.096 test[1276:207] 154550038129946624 

¿Qué estoy haciendo mal? No tengo idea de cómo explicar este comportamiento.

Respuesta

5

NSDecimalNumber carece del método unsignedLongLongValue, por lo que hereda una implementación predeterminada de NSNumber. Las únicas formas de obtener el valor de NSDecimalNumber son obtener una estructura NSDecimal o double. El error de conversión se introduce en el proceso de conversión de NSDecimalNumber a double.

+0

No lo entendí desde el principio y publiqué mi propia respuesta, pero ahora la obtengo y tu respuesta es la mía. Para otros, que, al igual que yo, no entendieron por completo: el decimal dentro de 'NSDecimalNumber' se convierte en el doble antes de enviarlo a unsigned long long. De todos modos, creo que es un error fundamental de SDK. –

+0

@AlexanderN. No estoy de acuerdo con que esta sea una falla fundamental del SDK: si te mantienes dentro de 'NSDecimalNumber's, obtienes una precisión sólida, que es lo único que les importa a los diseñadores del SDK. Las conversiones a otros tipos están ahí por mera conveniencia; su uso viene con la comprensión de que se puede perder cierta precisión debido a las diferencias en la representación. – dasblinkenlight

+0

Lo entiendo. Pero, ¿no crees que es un poco raro - arrojar un entero (en este caso) decimal a entero de larga duración y perder precisión, como en el fundido de float-int? –