我有可以从 21:00 到 04:00 的时间表。
大多数情况下,这些时间表可能会超过 00:00 小时标记。
现在我还必须添加从 00:00 到 23:59 的正常时间表。
我想计算一个交叉点。
目前我正在使用
if(((mytime1.start_time <= mytime2.end_time) && (mytime2.start_time <= mytime1.end_time))).
当考虑到跨日时间表时,我仍然没有有效的防呆逻辑,请帮忙。
bool DoIntervalsOverlap(int s0, int e0, int s1, int e1)
{
return s0 - e0 <= (unsigned int) s0 - e1 || s1 - e1 <= (unsigned int) s1 - e0;
}
首先,请注意,本质上,所有算术都是无符号的。在s0 - e0 <= (unsigned int) s0 - e1
,e1
转换为unsigned int
匹配s0
,并s0 - e0
转换unsigned int
为匹配(unsigned int) s0 - e1
。下面,我假设所有算术都是无符号的。
回想起来,我希望我以相反的顺序写了这些条款。让我们现在解决这个问题。s0 - e0 <= s0 - e1
相当于e0 - s0 >= e1 - s0
。(即使在无符号算术中也是如此。)现在我们可以将时间e0e0 - s0
和e1转换为以s0为原点的参考系。在这个框架中,一天中比原始s0更早的任何时间都被包装成大的正数。所以,午夜的缠绕已经消失了。我们只有从s0测量的非负时间。然后我们看到这是在问“是e1,从s0测量,小于或等于e0e1 - s0
e0 - s0 >= e1 - s0
?” 这个问题相当于“ e1在 [ s0 , e0 ] 内吗?”</p>
因此,这两个条件问“ e1在 [ s0 , e0 ] 内还是e0在 [ s1 , e1 ] 内?” 如果任一区间在另一个区间内结束,则区间重叠。如果两者都没有在另一个内部结束,则它们不会重叠。
按顺序考虑第一个间隔中的每个时刻。如果这些时刻都不与第二个区间的开始重合,那么这两个区间不相交,除非区间从一开始就已经相交,在这种情况下,第一个区间的第一个时刻将出现在第二个区间的类似通道中间隔。因此,如果第一个区间的起点和终点是 (l1, r1),第二个区间的起点和终点是 (l2, r2),我们可以通过查看 l1 是否包含在范围 [l2, r2] 以及是否包含 l2 来检查在 [l1, r1] 范围内。如果 lx 在数值上不大于 rx,那么这是一个简单的检查,例如 (l1 >= l2) && (l1 <= r2)。如果 lx 大于 rx 则它是一个环绕间隔,您可以检查是否 (l2 >= l1) || (l2 <= r1)。