c - 为什么gmtime是这样实现的?

标签 c time

我偶然发现了 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 是距 epoch 的距离。此外,似乎每年必须单独计算 LEAPYEAR——当前日期计算数十次,而遥远的 future 日期计算更多次。我有以下算法来做同样的事情(在这种情况下来自 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,为什么?

最佳答案

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

也许这就是答案

关于c - 为什么gmtime是这样实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3136341/

相关文章:

java - 如何用Java编写自己的mupdf实现?

performance - 如何在 Splunk 中有效地对长时间跨度进行采样?

string - 为什么打印 time.Time 和指向 time.Time 的指针具有相同的结果?

r - 计算比较连续时间段的值的函数

c - C中链表删除节点

在c中将整数转换为32位二进制

r - 确定哪个id的时间点早于R中的另一个时间点

time - 我如何在 Go 语言中格式化时间

cstring 字符串; vs 字符字符串;

java - 使用 SHA1 从多个值计算聚合