17

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)很难弄清楚。有人可以解释一下它是如何工作的吗?关于这个实现的任何参考?

4

2 回答 2

14

year & 3是一样的year % 4。那里没有那么棘手,它只是代表通常的 4 年周期。

year & 15是一样的year % 16

因此,如果年份没有被 4 整除,或者它没有被 16 整除但被 25 整除,则它不是闰年。这意味着 25 的每个倍数都不是闰年,除非它也是16 的倍数。由于 16 和 25 没有任何公因数,因此唯一同时满足两个条件的情况是年份是 16*25 的倍数,即 400 年。4*25 的倍数将被视为非闰年,占 100 年周期。

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

于 2012-03-24T15:40:36.610 回答
5

如果一个数既能被 16 整除又能被 25 整除,那么它就可以被 25 的四倍(100)和 25 的 16 倍(400)整除。

于 2012-03-24T15:21:43.027 回答