2016-06-15 7 views
2

У меня есть Windows, FILETIME:Округление FILETIME в C# для размещения FAT округления

64-битное значение, представляющее количество 100-наносекундных интервалов с 1 января 1601 (UTC))

и мне нужно округлить UP до ближайшего даже второго, как описано here.

код у меня до сих пор:

 var originalDt = DateTime.FromFileTimeUtc(input); 

     // round it UP to the nearest Second 
     var newDt = originalDt.AddMilliseconds(1000 - originalDt.Millisecond); 

     // then if our new Second isn't even 
     if (newDt.Second % 2 != 0) 
     { 
      // add one second to it, then it'll be even 
      newDt = newDt.AddSeconds(1); 
     } 

     return newDt.ToFileTimeUtc(); 

не совсем работа ... получается 130790247821478763 в 130790247820008763, я после 130790247800000000.

Математика не моя самая сильная тема. .. могу ли я просто сбросить эти последние четыре цифры безопасно? Или я должен забыть приведенный выше код и полностью удалить последние восемь цифр? Или ... по-другому?

+0

округлить до кратного N с 'value = N * (значение/N + N-1)' –

ответ

3

Вместо того, чтобы бороться с DateTime объектом, вы могли бы, возможно, более легко просто сделать сырую математику:

Если input этого числа 100 наносекунд, а затем:

/10 для числа микросекунд;
/10,000 для количества миллисекунд;
/10,000,000 для количества секунд;
/20,000,000 для количества «двух секунд»;

Итак:

input = input/20000000 * 20000000; 

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

Но вы сказали, что вы хотели огибая UP:

input = (input/20000000 + 1) * 20000000; 

Это добавляет один «две секунды» в небольшом количестве, прежде чем факторинг его снова.

Педантично, если input был на ровно двухзначный знак, то это добавило бы две секунды к нему. Чтобы исправить это:

if (input % 20000000!=0) { 
    input = (input/20000000 + 1) * 20000000; 
} // if 

Это проверяет, существует ли какая-либо дробная «двухсекундная», прежде чем принимать решение об этом. Я оставлю это до вас, чтобы добавить ли этот дополнительный чек ...

@Matthew Уотсон указывает на то, что обычные программисты трюк для указанной задачи является предварительно добавить не совсем достаточно, чтобы свернуть input до следующей «двухсекундной», затем идите вперед и выполните разделить-затем-умножить. Если input было по минимуму, что будет катить его на:

const long twoSeconds = 20000000; 
    ... 
    input = (input + twoSeconds - 1)/twoSeconds * twoSeconds; 
+0

Точно то, что я тоже собирался. –

+1

На самом деле, я думаю, вы могли бы сделать 'input = ((вход + 20000000 - 1)/20000000) * 20000000;', чтобы избежать необходимости вычисления модуля –

+0

@Matthew Yup! Теперь объясните это самопознанному не математику –

0

Работа с клещами сырья, то вокруг этих до двух-секундных интервалов. Это проще, чем пытаться добавить или удалить вещи после запятой.

const long twoSecondsInTicks = 20000000; // 20 million 
long twoSecondIntervals = originalDt.Ticks/twoSecondsInTicks; 
if (originalDt.Ticks % twoSecondsInTicks != 0) ++twoSecondIntervals; 
var newDt = new DateTime(twoSecondIntervals * twoSecondsInTicks); 
0

Вашей проблема заключается в округление до ближайшей второй линии:

// round it UP to the nearest Second 
var newDt = originalDt.AddMilliseconds(1000 - originalDt.Millisecond); 

вы оставить нетронутую доли миллисекундыoriginalDt.Millisecond является значения а целого числа), микро - и nano - seconds; она должна быть

// round it UP to the nearest Second 
var newDt = originalDt.AddTicks(- (originalDt.Ticks % TimeSpan.TicksPerSecond)); 

при работе с клещей, то наименьшее возможно блок даты и времени, вы получите ожидается 130790247820000000без наносекунд (...8763)

 Смежные вопросы

  • Нет связанных вопросов^_^