int
是否可以使用一些位运算符从表示为(格式 YYYYMMDD,例如 20110401)的日期中提取月份?
如果是这样,怎么办?
编辑:我目前正在使用 20110401 % 10000 / 100。我认为按位可能会更快。DateTime.Parse 等对于我想要做的事情来说太慢了。
int
是否可以使用一些位运算符从表示为(格式 YYYYMMDD,例如 20110401)的日期中提取月份?
如果是这样,怎么办?
编辑:我目前正在使用 20110401 % 10000 / 100。我认为按位可能会更快。DateTime.Parse 等对于我想要做的事情来说太慢了。
不,因为位运算符使用数字的二进制表示。您的日期使用十进制表示进行编码。
您可以使用算术运算符来做到这一点:
int date = 20110401;
int day = date % 100;
int month = (date / 100) % 100;
int year = date / 10000;
20110301
(base 10) 作为整数将在位级别上完全不同地表示,实际上是1001100101101101111011101
(base 2)。使用位级操作从该位串中提取月份并非易事。
备择方案:
对整数做一些涉及 mod 的基本数学运算
将 转换int
为字符串,然后提取相关数字并将它们转换回整数。
或者更好的是,为此使用一些已经测试过的库函数。
位级操作不是解决这个问题的好方法。
如果可以的话,使用按位运算可能容易出错。您可以通过除法和模运算来处理数字。
您还可以将其转换为字符串,解析月份字符,然后再转换回 int。
这是 C# 中的一些示例代码
int date = 20119420;
int month = 0;
// using good old math
month = (date / 100) % 100;
// using string parsing
month = int.Parse(date.ToString().Substring(4, 2));
如果您以二进制格式表示日期,则可以通过按位运算有效地提取月份,例如,5 位表示月份的日期,4 位表示月份编号,其余表示年份,而不是十进制数字。对于您的示例,日期将是 (2011 << 9) + (4 << 5) + 1 (当然不等于 20110401)。要使用按位运算从此类表示中提取字段:
int year = date >> 9;
int month = (date >> 5) & 0xF;
int day = date & 0x1F;
正如 Mark Byers 所提到的,另一种方法是使用结构,例如,
typedef struct {
short year;
char month;
char day;
} Date;
您可以在堆栈上传递这些,按名称提取字段,并将它们初始化为
Date d = { 2011, 4, 1};
或者,在 C99 中,
Date d = { .year = 2011, .month = 4, .day = 1 };
所以我知道这是一篇非常古老的帖子,但这实际上是我们班的作业,我有一个压缩日期和一个仅使用按位运算的提取日期函数:
//Compress Date
int compressDate(int month, int day, int year)
{
int date = year;
date <<= 4;
date |= month;
date <<= 6;
date |= day;
return date;
}
//Extract Date
void extractDate(int date, int& month, int& day, int& year)
{
int dayMask = 63;
int monthMask = 15;
int yearMask = 4095;
day = date & dayMask;
date >>= 6;
month = date & monthMask;
date >>= 4;
year = date & yearMask;
}
当您使用 compressDate(1, 25, 2019) 之类的函数执行压缩日期函数时,它会返回数字:2067545,而 extractDate 函数的工作顺序正好相反。这样做的原因是按位运算符比使用数学运算符更快。