为什么gmtime以这种方式实现?

我碰巧发现了Minix的gmtime函数。 我对从纪元以来几天计算年份数的位感兴趣。 以下是这一点的内容:

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是距离纪元的距离。 此外,LEAPYEAR似乎必须每年单独计算 – 当前日期数十次,未来日期更多。 我有以下算法做同样的事情(在这种情况下从ISO-9601时代(0年= 1 BC)而不是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的开发人员是Smart People,他们为了一个理由而采用了他们的方式,并且可能比我更了解C,为什么呢?

这是纯粹的推测,但MINIX的要求可能比执行速度更重要,例如简单,易于理解和简洁? 毕竟,有些代码印在教科书上。

将您的代码作为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 

也许这是一个答案

你的方法听起来很合理,但要让它在EPOCH_YR = 1970上运行起来有点困难,因为你现在在几个周期的中期循环。

你能看出你是否有相同的情况,看看它是否仍然更好?

你肯定是否应该在任何高性能代码中使用gmtime()实现是有争议的。 在任何紧密循环中都要做很多繁忙的工作。

正确的做法。 你肯定想去找O(1)算法。 可以在没有ado的玛雅日历中工作。 检查最后一行:dayno限制为0..364,尽管在闰年它需要在0..365范围内。 这条线之前有类似的缺陷。