.NET AddDays проблема - PullRequest
       0

.NET AddDays проблема

12 голосов
/ 14 марта 2012

Следующие 2 строки добавляют ту же сумму к той же дате, и часть даты результатов совпадает, но каким-то образом есть разница во временной части!

(new DateTime(2000,1,3,18,0,0)).AddDays(4535);   
(new DateTime(2000,1,3,18,0,0)).AddMonths(149);

вы получите разницу15 секунд, и с обоими, по крайней мере, с округлением до дней, я не знаю, почему это произошло, но это происходит только с AddDays, но не с AddMonths (даже с добавлением тысяч месяцев)


Редактировать 1

Итак, я попытался создать пример проекта, но безуспешно.Если я запускаю свой основной проект и помещаю строки с образцами в часы, то я получаю 2 отдельных значения, если я начинаю с нуля, проблема не в этом.Проект 3.5, c #, vs2010, win7hp x64 (proj: x86).Я пытаюсь воспроизвести это также в новом небольшом проекте, я напишу, если он у меня будет.

Это мои результаты в основном проекте (в зависимости от часов!):

(new DateTime(2000, 1, 3, 18, 0, 0)).AddDays(4535).Ticks    
 634743432153600000 long

(new DateTime(2000, 1, 3, 18, 0, 0)).AddMonths(149).Ticks   
 634743432000000000 long

Редактировать 2

Мне удалось сузить его еще больше.У нас есть самодельный компонент, панель основания, мы рисуем на нем с помощью DirectX.Если я сделаю это visible = false, чем visible = true, то возникнет ошибка, прежде чем visible = true (или show ()), вычисление будет правильным.Что в мире может быть там, что результат получает что-то другое формулы, где переменная не используется.Культура не влияет на компонент ..

Ответы [ 2 ]

4 голосов
/ 14 марта 2012

Здесь они дают одинаковый результат:

var d1 = (new DateTime(2000, 1, 3, 18, 0, 0)).AddDays(4535).Ticks;
var d2 = (new DateTime(2000, 1, 3, 18, 0, 0)).AddMonths(149).Ticks;

d1 == d2 == 634743432000000000

(Тик - это внутренний «квант» времени DateTime. Он довольно короткий. Это одна десятая миллионная доли секунды

Я добавлю, что даже Mono (независимая реализация .NET) дает тот же результат http://ideone.com/krySY (Ideone использует mono)

Принимая во внимание последние написанные вами вещи, это довольно просто: повреждение памяти. Повреждение памяти может делать очень случайные вещи. Это, вероятно, один из тех: -)

3 голосов
/ 04 мая 2012

Это результат того, что DirectX молча меняет режим вычисления с плавающей запятой ЦП, чтобы всегда использовать одинарную точность.Иногда это делается для повышения производительности: использование одинарной точности может быть немного быстрее, чем использование двойной точности.См. Описание флага FpuPreserve в документации MSDN для перечисления DirectX CreateFlags.

Причина, по которой другие не могут воспроизвести это, заключается в том, что они этого не делаютВызовы DirectX.

Аргументом AddDays является double.Это значение умножается на коэффициент масштабирования, чтобы получить время в миллисекундах.Именно этот расчет вызывает ошибку.

Учтите:

double value = 4535;
int scale = 86400000;
long milliseconds = (long) ((value * scale) + ((value >= 0.0) ? 0.5 : -0.5));
long milliseconds2 = (long)((float)(value * scale) + ((value >= 0.0) ? 0.5 : -0.5));
Console.WriteLine(milliseconds2 - milliseconds);

Выражение для milliseconds2 содержит приведение к float, которое имитирует эффект форсирования DirectX одинарной точностирасчеты.Это выведет 15360, в точности разницу, которую вы найдете.

В отличие от этого, AddMonths принимает целое число и не использует арифметику с плавающей точкой.Таким образом, результат является точным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...