2010-12-16 269 views
4

Voici le codeNSDate et double problème de précision

NSDate* d = [NSDate dateWithTimeIntervalSince1970:32.4560]; 
double ti = [d timeIntervalSince1970]; 
NSLog(@"Interval: %f %f %f %f",ti,32.4560,ti*1000.0,32.4560*1000.0); 

la sortie est

Intervalle: 32,456000 32,456000 32455,999970 32456,000000

Pourquoi NSDate retourner la valeur qui perd quelques precisions?

Répondre

7

Ce n'est pas le problème de NSDate lui-même. C'est dans la nature des nombres flottants eux-mêmes. Je crois que NSDate conserve sa date de l'époque OS X (2001), pas l'époque UNIX (1970). Que la différence dans les deux époques soit x.

Alors ce qui se passe est la suivante:

NSDate* d = [NSDate dateWithTimeIntervalSince1970:32.4560]; 
// at this point, d keeps 32.4560 + x 
double ti = [d timeIntervalSince1970]; 
// ti is then (32.4560+x)-x 

Cependant, le point flottant n'a pas une précision infinie. Ainsi, +x puis -x peuvent introduire une légère erreur dans le calcul.

Pour en savoir plus, lisez par ex. this Wikipedia article.

Si vous utilisez l'époque OS X, vous obtenez ce que vous attendez naïvement:

NSDate* d = [NSDate dateWithTimeIntervalSinceReferenceDate:32.4560]; 
// at this point, d keeps 32.4560 + 0 
double ti = [d timeIntervalSinceReferenceDate]; 
// ti is then (32.4560+0)-0, which is 32.4560 even in the floating point world. 
+0

Merci, je ne savais pas époque OSX 2001. – teerapap

+0

Peut-être que je l'ai utilisé la terminologie « époque OpenStep " au lieu. Voir http://docs.sun.com/app/docs/doc/802-2112/6i63mn64s?l=fr&a=view#05.Classes-81 Je crois que la spécification OpenStep est apparue avant 2001. Il est très ambitieux de les définir. date de référence dans le futur. – Yuji