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

时间:2019-08-20 09:32:32

标签: c algorithm

我需要在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;
...

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

4 个答案:

答案 0 :(得分:4)

我建议不要使用返回值012,而建议使用<00>0。这更常见,与strcmpqsortbsearch的语义匹配,并且可以通过简单的减法并与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字段的常规值有效。对于“通常”年份值,这是一个合理的假设。如果year对于abs(a.year) + abs(b.year) > INT_MAX字段无效。要处理year .. INT_MIN整个范围内的INT_MAX值,必须更改算法。

答案 1 :(得分:0)

在比较时间戳时,有2个问题起作用

年份范围

如果.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);
}

答案 2 :(得分:0)

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

参见:Using Contiguous Memory of C Struct Members

您可以像这样尝试逐字节比较:

#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;
}



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

答案 3 :(得分:-1)

这里有一个小改进:

您的PC正在使用二进制文件运行,因此基数2是他最好的选择

您可以替换:

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

依据(您的值均小于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);

但是正如我上面提到的,当进行优化时,概要分析是您的朋友。


P.s。

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