我有一个以不寻常的方式存储的一周范围内的日期数组。
日期以此数字格式存储:12150
从左到右:
第1位代表日:1 =星期日,2 =星期一,3 =星期二,....,7 =星期六
接下来的两位数表示24小时制中的小时:00 =午夜,23 =晚上11点
接下来的两位数代表分钟:00-59
鉴于输入日期,开始日期和结束日期,我需要知道输入日期是否在开始日期和结束日期之间。
我现在有一个算法,我认为可以100%的时间工作,但我不确定。
无论如何,我认为可能有一种更好更简单的方法,我想知道是否有人知道该算法是什么。
如果不是,如果有人可以仔细检查我的工作并确认它确实对100%的有效案例有效,那就太酷了。
我现在拥有的是:
if (startDate < inputDate &&
endDate > inputDate) {
inRange = yes;
}
else if (endDate < startDate) {
if((inputDate + 72359) > startDate &&
(inputDate + 72359) < endDate) {
inRange = yes;
}
else if((inputDate + 72359) > startDate &&
(inputDate + 72359) < (endDate + 72359)) {
inRange = yes;
}
}
答案 0 :(得分:1)
怎么样
const int MAX = 72460; // Or anything more than the highest legal value
inRange = (MAX + inputDate - startDate) % MAX <
(MAX + endDate - startDate) % MAX;
这当然假设所有日期都很好(根据您的规格)。
这解决了开始是“结束”之后的情况。 (例如,如果开始是星期三,结束是星期一,则星期五在范围内)
可能需要一秒钟才能看到(这可能不太好,因为可读性通常是最重要的),但我认为它确实有效。
这是基本技巧:
Legend: 0: Minimum time M: Maximum time S: Start time 1,2,3: Input Time test points E: End Time The S E => Not in range 2 In range 3 > E => Not in range The S > E case 0 M Original -1--E----2---S--3-- Add Max -------------------1--E----2---S--3-- Subtract StartDate ------1--E----2---S--3-- % Max S--3--1--E----2---- 1 In range 2 > E => Not in range 3 In range
如果你真的想要坚果(并且更难以破译)
const int MAX = 0x20000;
const int MASK = 0x1FFFF;
int maxMinusStart = MAX - startDate;
inRange = (maxMinusStart + inputDate) & MASK <
(maxMinusStart + endDate) & MASK;
由于MAX的值并不重要(只要它超过最大格式良好的值),我们可以做的,它应该稍快一点(按位和交易模数),我们可以自由地选择一个使我们的计算变得容易的。
(当然,如果您真正需要的话,可以将<
替换为<=
答案 1 :(得分:1)
该格式的日期存在一些逻辑错误。由于缺少月份和年份信息,您无法知道缺少哪个日历日。例如50755可能是2009年3月12日星期四,但它可能恰好是一周前,或者提前18周。如果该格式的任何日期在任何其他2个日期之间,那么对您来说永远不会100%确定。
答案 2 :(得分:1)
此处内部if
的条件永远不会成立,因为endDate < startDate
:
if (endDate < startDate) {
if((inputDate + 72359) > startDate &&
(inputDate + 72359) < endDate) {
// never reached
inRange = yes;
}
以下如果也不是最优的,因为第一部分总是正确而第二部分与inputDate < endDate
完全相同:
if((inputDate + 72359) > startDate &&
(inputDate + 72359) < (endDate + 72359))
我想你想要这样的东西:
if (startDate < endDate)
inRange = (startDate < inputDate) && (inputDate < endDate);
else
inRange = (startDate < inputDate) || (inputDate < endDate);
答案 3 :(得分:0)
如果你真的希望它在范围
,你应该使用&gt; =和&lt; =说我选择这个日期10000或72359,你将如何处理这个?是否在范围内?
我也不知道startDate和endDate的值,因为你没有初始化它,纠正我,如果我错了,未初始化的变量将从0开始或为null或''
所以我假设startDate = 10000和endDate 72359
btw为什么你选择这种数组(作为int或字符串值?)为什么第一个值是白天?不是日期的例子:
010000 - &gt;日期00:00的日期
312359 - &gt;这个月的第31日23:59
但这取决于你:D
很抱歉,如果我错了,我只在大学学习算法课,那是5年前的事:D
答案 4 :(得分:0)
更好的方法可能是规范化您的数据,将所有星期几的值转换为相对于开始日期。像这样:
const int dayScale = 10000; // scale factor for the day of the week
int NormalizeDate(int date, int startDay)
{
int day = (date / dayScale) - 1; // this would be a lot easier if Sunday was 0
int sday = startDay - 1;
if (day < sday)
day = (day + 7 - sday) % 7;
return ((day+1) * dayScale) + (date % dayScale);
}
int startDay = startDate / dayScale; // isolate the day of the week
int normalizedStartDate = NormalizeDate(startDate, startDay);
int normalizedEndDate = NormalizeDate(endDate, startDay);
int normalizedInputDate = NormalizeDate(inputDate, startDay);
inRange = normalizedInputDate >= normalizedStartDate &&
normalizedInputDate <= normalizedEndDate;
我很确定这将按照书面形式运作。无论如何,这个概念更加清晰,可以进行多重比较。
答案 5 :(得分:0)
我发现的最简单的解决方案是:
表示x您的通用时间和S,E分别为开始时间和结束时间(0
dat %>%
summarise_all(~mean(.) * 100) %>%
gather(key, value) %>%
separate(key, into = c("item", "column"), sep = "_") %>%
spread(column, value)
如果x在开始时间和结束时间之间,则此函数返回TRUE,否则返回FALSE。 它还会照顾开始时间,而不是结束时间(例如,您从20:00开始工作并在04:00结束,23:13将返回TRUE)
我必须说,考虑到乘法,它在速度上可能不是最有效的,但绝对是最紧凑的(而且是恕我直言)
编辑: 我找到了一个更优雅,更有效的解决方案:
f(x) = [(x-S) * (x-E) * (E-S) < 0]
您可以将XOR替换为“不同”运算符(!=)
我解释一下:
第一个公式来自考虑关系不平等的研究:
如果S 因此,如果x在S和E之间,则总数为负 如果S> E: 因此,如果x大于S或小于E,则总数为负 要得出最终方程,请用3个项分解第一个公式: 这些术语的乘积只有在全部为负数(true,true,true)或只有一个为负数而另一个为正数(true,false,false,但顺序无关紧要)时才为负数
因此,可以通过 这些解决方案可以应用于周期系统的任何类似问题,例如检查角度x是否在由两个角度S和E形成的圆弧内。
只要确保所有变量都在0和系统周期之间即可(圆弧为2PI,圆形为24h,小时为24 * 60 * 60,以秒为单位.....等等)< / p>
f(x) = (x<S) XOR (x<E) XOR (E<S)
...............S.....E..........
(x-S)----------+++++++++++++++++
(x-E)----------------+++++++++++
(E-S)+++++++++++++++++++++++++++
total++++++++++------+++++++++++
...............E.....S..........
(x-S)----------------+++++++++++
(x-E)----------+++++++++++++++++
(E-S)---------------------------
total----------++++++-----------
(x-S)<0 => x<S
(x-E)<0 => x<E
(E-S)<0 => E<S