Я произошел через источник для функции gmtime Minix. Я интересовался битом, который вычислил число года со дней с эпохи. Вот кишки того бита:
http://www.raspberryginger.com/jbailey/minix/html/gmtime_8c-source.html
http://www.raspberryginger.com/jbailey/minix/html/loc__time_8h-source.html
#define EPOCH_YR 1970
#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
int year = EPOCH_YR;
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
Похоже, что алгоритм является O (n), где n является расстоянием с эпохи. Кроме того, кажется, что ВИСОКОСНЫЙ ГОД должен быть вычислен отдельно в течение каждого года – десятки времен для текущих дат и намного больше для дат далеко в будущем. У меня был следующий алгоритм для того, чтобы сделать то же самое (в этом случае с эпохи ISO 9601 (год 0 = 1 до н.э), а не эпохи UNIX):
#define CYCLE_1 365
#define CYCLE_4 (CYCLE_1 * 4 + 1)
#define CYCLE_100 (CYCLE_4 * 25 - 1)
#define CYCLE_400 (CYCLE_100 * 4 + 1)
year += 400 * (dayno / CYCLE_400)
dayno = dayno % CYCLE_400
year += 100 * (dayno / CYCLE_100)
dayno = dayno % CYCLE_100
year += 4 * (dayno / CYCLE_4)
dayno = dayno % CYCLE_4
year += 1 * (dayno / CYCLE_1)
dayno = dayno % CYCLE_1
Это работает в O (1) для любой даты и похоже на него, должно быть быстрее даже для дат обоснованно близко к 1970.
Так, при предположении, что разработчики Minix являются Умными Людьми, которые сделали это их путь по Причине, и вероятно знать немного больше о C, чем, я делаю, почему?
Это чистое предположение, но, возможно, MINIX предъявляла требования, которые были важнее скорости выполнения, такие как простота, легкость понимания и краткость? В конце концов, часть кода была напечатана в учебнике.
Ваш метод кажется правильным, но немного сложнее заставить его работать для EPOCH_YR = 1970, потому что вы сейчас находитесь в середине цикла на нескольких циклах.
Можете ли вы посмотреть, есть ли у вас эквивалент для этого случая, и посмотреть, лучше ли он?
Вы, конечно, правы, что спорный вопрос, следует ли использовать эту реализацию gmtime () в каком-либо высокопроизводительном коде. Это очень напряженная работа в любых жестких кругах.
Прогнал ваш код как y2 minix-код как y1 Solaris 9 v245 и получил эти данные профилировщика:
%Time Seconds Cumsecs #Calls msec/call Name
79.1 0.34 0.34 36966 0.0092 _write
7.0 0.03 0.37 1125566 0.0000 .rem
7.0 0.03 0.40 36966 0.0008 _doprnt
4.7 0.02 0.42 1817938 0.0000 _mcount
2.3 0.01 0.43 36966 0.0003 y2
0.0 0.00 0.43 4 0. atexit
0.0 0.00 0.43 1 0. _exithandle
0.0 0.00 0.43 1 0. main
0.0 0.00 0.43 1 0. _fpsetsticky
0.0 0.00 0.43 1 0. _profil
0.0 0.00 0.43 36966 0.0000 printf
0.0 0.00 0.43 147864 0.0000 .div
0.0 0.00 0.43 73932 0.0000 _ferror_unlocked
0.0 0.00 0.43 36966 0.0000 memchr
0.0 0.00 0.43 1 0. _findbuf
0.0 0.00 0.43 1 0. _ioctl
0.0 0.00 0.43 1 0. _isatty
0.0 0.00 0.43 73932 0.0000 _realbufend
0.0 0.00 0.43 36966 0.0000 _xflsbuf
0.0 0.00 0.43 1 0. _setbufend
0.0 0.00 0.43 1 0. _setorientation
0.0 0.00 0.43 137864 0.0000 _memcpy
0.0 0.00 0.43 3 0. ___errno
0.0 0.00 0.43 1 0. _fstat64
0.0 0.00 0.43 1 0. exit
0.0 0.00 0.43 36966 0.0000 y1
Может быть, это ответ