闰年检查使用按位运算符(惊人的速度)

有人在JSPerf下降了一个惊人的快速实施检查闰年的ISO日历(链接: 奇怪的位操纵 ):

function isLeapYear(year) { return !(year & 3 || year & 15 && !(year % 25)); } 

使用Node.js,我快速检查了两个我知道的单线程实现。

 function isLeapClassic(y) { return (y % 4 == 0) && !(y % 100 == 0) || (y % 400 == 0); } function isLeapXOR(y) { return (y % 4 == 0) ^ (y % 100 == 0) ^ (y % 400 == 0); } function isLeapBitwise(y) { return !(y & 3 || y & 15 && !(y % 25)); } //quick'n'dirty test on a small range! //works with negative integers too for (var i = 1900; i <= 2100; i++) { console.log( "year = %d,\t%d%d%d", i, isLeapClassic(i), isLeapXOR(i), isLeapBitwise(i) ); } 

它按预期工作,但我的问题是我不知道如何。 我知道((a % b) == (a & (b-1))当b是2的幂时,所以(year % 4) == (year & 3) ,而year & 15 && !(year % 25)很难搞清楚,有人可以解释一下它是如何工作的吗?有关这个实现的任何参考?

year & 3year % 4相同。 那里不那么棘手,它只是通常的4年周期。

year & 15year % 16

因此,如果年份不是均匀分配4年,也不是16年平均分配,而是25年平均分配,这不是一个闰年。这意味着25的每个倍数不是一个闰年,除非它也是是16的倍数。由于16和25没有任何共同的因素,唯一满足这两个条件的时间是年份是16 * 25或400年的倍数。 4 * 25的倍数将被认为不是闰年,占100年周期。

1900年不是闰年,因为它可以被100整除,2000 是闰年,因为它可以被400整除,2100年不会是闰年。

如果一个数字可以被16整除并且被25整除,那么25(100)和16(25(400))就可以被整除四次。

Interesting Posts