NSDate и проблема двойной точности

Вот код

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

вывод

Интервал: 32.456000 32.456000 32455.999970 32456.000000

Почему NSDate возвращает значение, которое теряет некоторые точности?


person teerapap    schedule 16.12.2010    source источник


Ответы (1)


Это не проблема самого NSDate. Это в природе самих чисел с плавающей запятой. Я считаю, что NSDate сохраняет свою дату с эпохи OS X (2001 г.), а не с эпохи UNIX (1970 г.). Пусть разница двух эпох равна х.

Затем происходит следующее:

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

Однако плавающая точка не имеет бесконечной точности. Таким образом, +x, а затем -x могут привести к небольшой ошибке в расчетах.

Для получения дополнительной информации прочитайте, например. эта статья в Википедии.

Если вы используете эпоху OS X, вы получите то, что наивно ожидаете:

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.
person Yuji    schedule 16.12.2010
comment
Спасибо, я не знал, что эпоха OSX - 2001 год. - person teerapap; 16.12.2010
comment
Возможно, мне следовало использовать вместо этого терминологию эпохи OpenStep. См. docs.sun. .com/app/docs/doc/802-2112/ Я считаю, что спецификация OpenStep появилась до 2001 года. С их стороны довольно амбициозно установить дату отсчета в будущем. - person Yuji; 16.12.2010