Проблема с COleDateTime.
От: rus blood Россия  
Дата: 08.04.09 16:05
Оценка: 10 (2)
#Имя: FAQ.mfc.COleDateTime.trouble
Здравствуйте, Avdeev, Вы писали:

A>Иными словами к дате "29.12.1899 23:55:00" добавляем 5 минут и ожидаем увидеть "30.12.1899 00:00:00" а вместо этого нам возвращается "28.12.1899 00:00:00" — что очень уж странно!!! При этом если прибавлять нечто отличное от 5 минут то сложение происходит верно, также всё верно если вычесть 5 минут из "30.12.1899 00:00:00". Кто-нибудь сталкивался с этой проблемой? Я думаю, что это баг ребят из майкрософта.


A>Здесь дело не в округлении, я дебажил этот код.


Это ошибка в округлении, которая вместе с "вывернутой" системой счисления для "отрицательных" дат дает такой эффект.

OLE дата хранит время как double число. Целая часть — кол-во дней с 30.12.1899, дробная — часть дня. Для "отрицательных" дат используется "вывернутая" система — целые части по прежнему нумеруют дни назад в прошлое, а дробная часть определяет часть дня вперед, в будущее.

Например, — 2.5 будет 2 дня назад в прошлое от 30.12.1899, плюс полдня вперед в будущее. Т.е. в итоге получается полдень 28.12, а не 27.12.

Отображение дат DATE на "плоский" double примерно такое.


double = 2 * ceil — DATE
DATE = 2 * floor — double.

С математикой все в порядке, а ошибка в точности вычислений и округлении. При добавлении 5 минут получается "почти" ноль, но из-за неточности вычисления — маленькое отрицательное число. У меня было где-то около -10^(-17). Далее, "плоское" отрицательное double-число около нуля после конвертации соответствует значению для DATE примерно -1.999999... , что с округлением дает -2. Суть в том, что в "вывернутой" системе счисления DATE между -1.9999... и -2 действительно около 2 дней разницы, и код получается чувствительным к ошибкам округления.
Имею скафандр — готов путешествовать!
coledatetime mfc
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.