繁体   English   中英

比较两个日期时间戳的算法

[英]Algorithm to compare two date time stamps

我需要在 C 中实现时间戳比较(不使用任何库)。

我正在尝试找出最佳算法,因为该例程将被大量使用。

我的输入数据是两个时间戳,a 和 b,每个时间戳包含以下内容:

year
month
day
hour
minute

在 C 伪代码中:

struct Timestamp {
    int year;
    int month;
    int day;
    int hour;
    int minute;
};

struct Timestamp a;
struct Timestamp b;

我正在尝试几种方法,包括嵌套 if 和组合每个值的开关:

int timestamp_comparison(int a, int b) {
    if(a>b) return 2;
    if(a=b) return 1;
    if(a<b) return 0;
}
...
c_year = timestamp_comparison(a.year, b.year);
c_month = timestamp_comparison(a.month, b.month);
c_day = timestamp_comparison(a.day, b.day);
c_hour = timestamp_comparison(a.hour, b.hour);
c_minute = timestamp_comparison(a.minute, b.minute);

comparison = c_year * 10000 + c_month * 1000 + c_day * 100 + c_hour * 10 + c_minute;
...

但我想知道是否有一个我可以利用的算法。 我不喜欢使用外部库。

我建议不要使用返回值012 ,而是使用<00>0 这个比较常见,匹配strcmp等、 qsortbsearch的语义,可以使用简单的减法和与 0 的比较来实现。

/*
 * @retval <0 if a < b
 * @retval 0 if a == b
 * @retval >0 if a > b
 */
int compare_timestamps(struct Timestamp a, struct Timestamp b)
{
    int result;

    result = a.year - b.year;
    if(result != 0) return result;

    result = a.month - b.month;
    if(result != 0) return result;

    result = a.day - b.day;
    if(result != 0) return result;

    result = a.hour - b.hour;
    if(result != 0) return result;

    result = a.minute - b.minute;

    return result;
}

正如 Jim Mischel 的评论中提到的,该算法假设减法不会导致整数翻转。 这对monthdayhourminute字段的正常值有效。 这是对“通常”年份值的合理假设。 如果abs(a.year) + abs(b.year) > INT_MAX year字段abs(a.year) + abs(b.year) > INT_MAX 要处理整个INT_MIN .. INT_MAX范围内的year值,必须更改算法。

比较时间戳时,有两个问题会起作用

年份范围

如果.year的使用范围是[INT_MIN...INT_MAX] ,请避免a.year - b.year因为它可能会溢出。

主要价值

成员总是在他们的主要范围内吗? 示例: minute是否在 0-59 范围内?

是这样,一个简单的比较和返回 -1,0,1 使用常见的 C 习语(a>b) - (a<b) ,这是许多编译器识别并发出有效代码的东西。

int timestamp_compare(const struct Timestamp *ts2, const struct Timestamp *ts1) {
  if (ts1->year  != ts2->year)  return (ts2->year  > ts1->year)  - (ts2->year  < ts1->year);
  if (ts1->month != ts2->month) return (ts2->month > ts1->month) - (ts2->month < ts1->month);
  if (ts1->day   != ts2->day)   return (ts2->day   > ts1->day)   - (ts2->day   < ts1->day);
  if (ts1->hour  != ts2->hour)  return (ts2->hour  > ts1->hour)  - (ts2->hour  < ts1->hour);
  return (ts2->day > ts1->day) - (ts2->day < ts1->day);
}

如果不是,请形成分钟的线性计数,然后进行比较。

long long minutes(const struct Timestamp *ts) {
  return ((tbd_day_number(ts->year, ts->month, ts->day)*24LL + ts->hour)*60 + ts->minute;
}

int timestamp_compare(const struct Timestamp *ts2, const struct Timestamp *ts1) {
  long long m1 = minutes(ts1);
  long long m2 = minutes(ts2);
  return (m2 > m1) - (m2 < m1);
}

如果您的结构以排序方式包含其成员,例如在您的情况下(年份比月份更重要,依此类推...)并且由于在结构中,成员“最有可能”以连续方式存储:

请参阅: 使用 C 结构成员的连续内存

您可以尝试使用逐字节比较,如下所示:

#include <stdlib.h>

// members of struct are stored contigously
struct Timestamp
{
    int year;
    int month;
    int day;
    int hour;
    int minute;
};


int timestamp_comparison(const struct Timestamp a, const struct Timestamp b)
{
    unsigned i;
    unsigned struct_size = sizeof(struct Timestamp) / sizeof(int);
    const int* t1 = (const int*)&a;
    const int* t2 = (const int*)&b;

    // compare byte by byte
    for (i = 0; i < struct_size; i++)
    {
        if (*t1 != *t2)
            return *t1 - *t2;

        ++t1;
        ++t2;
    }

    return 0;
}

int main()
{
    // example
    struct Timestamp a = {1, 1, 2, 1, 1};
    struct Timestamp b = {1, 1, 1, 7, 1};
    int comp = timestamp_comparison(a, b);

    return 0;
}



我并不是说这比已经发布的答案更好,只是不同。 对于像您这样的任何其他结构,它的工作方式相同。

这里有一个小改进:

您的 PC 以二进制方式运行,因此以 2 为基数是他最擅长的

你可以替换:

comparison = c_year * 10000 + c_month * 1000 + c_day * 100 + c_hour * 10 + c_minute;

by(您的值都低于 4),因此您可以:

comparison = c_year * 256 + c_month * 64 + c_day * 16 + c_hour *4 + c_minute;

或者这个(可读性较差但“没有”算术):

comparison = c_year << 8 | c_month <<6 | c_day <<4 | c_hour <<2 | c_minute;

但是,如果您真的通过这种方式提高了速度,则只能通过分析进行验证。

根据您的数据,仅比较您需要的数据可能会更快:

int val;
if(1!=(val=timestamp_comparison(a.year, b.year)))
  return val;
if(1!=(val=timestamp_comparison(a.month, b.month)))
  return val;
if(1!=(val=timestamp_comparison(a.c_day, b.c_day)))
  return val;
if(1!=(val=timestamp_comparison(a.c_hour, b.c_hour)))
  return val;
return timestamp_comparison(a.c_minute, b.c_minute);

但正如我上面提到的,在优化方面,分析是你的朋友。


ps

if(a>b) return 2;
if(a=b) return 1;
if(a<b) return 0;

是一个有点不寻常的定义。 更常见的是:

if(a>b) return value >=1
if(a=b) return 0;
if(a<b) return value <=-1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM