我偶然发现了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纪元(Year 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开发人员是聪明的人,他们按照自己的方式进行操作并且有充分的理由,而且可能比我更了解C语言,那么为什么呢?