【问题标题】:Leap year check using bitwise operators (amazing speed)使用按位运算符进行闰年检查(惊人的速度)
【发布时间】:2012-04-08 19:37:57
【问题描述】:

JSPerf 上有人放弃了检查 ISO 日历闰年的惊人快速实现(链接:Odd bit manipulations):

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 &amp; (b-1)) 当 b 是 2 的幂,所以 (year % 4) == (year &amp; 3),但 year &amp; 15 &amp;&amp; !(year % 25) 很难弄清楚。有人可以解释一下它是如何工作的吗?关于这个实现的任何参考?

【问题讨论】:

  • 只是出于好奇:优化的用例到底是什么?
  • 速度惊人!如果您当然打算(重新)编写一个库,那会很有趣!
  • 我绝不会为了一纳秒的性能提升而牺牲可读性。
  • 如果您有数十亿条记录和性能问题,您应该考虑使用不同的语言。
  • 我写了一个详细的答案...见stackoverflow.com/a/11595914/733805

标签: javascript node.js leap-year


【解决方案1】:

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

year &amp; 15year % 16 相同。

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

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

【讨论】:

【解决方案2】:

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

【讨论】:

  • 那么它是如何被 400 整除的呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-11
  • 2021-08-07
  • 1970-01-01
  • 2019-08-09
  • 2022-12-10
  • 2016-12-19
  • 1970-01-01
相关资源
最近更新 更多