4

Here is the code

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);

the output is

Interval: 32.456000 32.456000 32455.999970 32456.000000

Why NSDate return the value which lose some precisions?

teerapap
  • 4,813
  • 7
  • 30
  • 39

1 Answers1

7

That's not the problem of NSDate itself. It's in the nature of the floating point numbers themselves. I believe NSDate keeps its date from the OS X epoch(2001), not the UNIX epoch (1970). Let the difference in the two epochs be x.

Then what happens is this:

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

However, the floating point doesn't have infinite precision. So, +x and then -x can introduce slight error in the calculation.

For more, read e.g. this Wikipedia article.

If you use the OS X epoch, you get what you naively expect:

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.
Yuji
  • 33,649
  • 3
  • 65
  • 85
  • Thanks, I didn't know OSX epoch is 2001. – teerapap Dec 16 '10 at 06:38
  • Maybe I should've used the terminology "OpenStep epoch" instead. See http://docs.sun.com/app/docs/doc/802-2112/6i63mn64s?l=en&a=view#05.Classes-81 I believe OpenStep specification came before 2001. It's quite ambitious of them to set the reference date in the future. – Yuji Dec 16 '10 at 08:34