C# - 将日期、月份、年份打包

3
在《以C#之音编程》一书中,作者给出了一个例子(包含源代码),展示了如何将日期(年、月、日——以数字形式表示)打包到32位整数中。在这个例子中,作者按照以下方式打包信息:
int iDate = (iYear << 9) | (iMonth << 5) | iDay;

如果我理解得正确,左移9位只能给我们一个512的值(如果计算每个位数,则为1023)。但是,当运行程序时,我注意到像2014(年份)这样的值可以被存储。这是怎么可能的,因为这个值很小?我是否误解了代码中的某一部分?无论我读、看还是玩弄代码都没有帮助我澄清这个问题。

3
好的,“2014 << 9 = 1031168”,你可以直接尝试验证一下。 - harold
int.Max = 2147483647这个数字远大于1031168(也就是20140101),所以…… - ManyRootsofAllEvil
2个回答

4

这个移位并不代表年份可以达到的最大值(即使你在计算中犯了错误,这也不是我们将9向左移的原因)。这个移位可以让你定义每个值所使用的范围。下面是一个ASCII码,展示了在值被移位后,在Int32中这些值如何被组织。

11111111111111111111111 1111 11111
-----------yyyyyyyyyyyY mmmM ddddD

由于日期最多只有31天,所以5位就足够了(32个可能的值)。对于月份,我们需要4位(16个可能的值),这可以容纳我们12种可能性。如果我们希望我们的智能日期方案在2048年后继续使用,年份至少需要12位。我们还有一些左侧的空间可供长期使用。

因此,这就是为什么我们将月份值向左移动5次,年份值向左移动9次的原因。另外,这也是为什么Int16不够用,我们需要比16位更多的位来存储我们的日期。


2
左移9位可能会得到512,如果您从1开始。然而,我认为正在发生的是假设最低的9位用于存储数字,但实际上较低的9位没有用于存储该值。左移9位将“使用的位”向左移动9位,释放出9个最低位。在这9位中,您只能存储512个不同的值(0到511),但这不是您用于年份的那一部分。
用图形来表达,假设值不“重叠”(除非您突然有16个或更多月,或32个或更多天),它最终会像这样:
syyy yyyy yyyy yyyy yyyy yyym mmmd dddd

未来几年有充足的空间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接