NSDate и проблема двойной точности - PullRequest
4 голосов
/ 16 декабря 2010

Вот код

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 возвращает потерянное значениенемного точности?

1 Ответ

7 голосов
/ 16 декабря 2010

Это не проблема самого 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.
...