--- title: Math.clz32() slug: Web/JavaScript/Reference/Global_Objects/Math/clz32 tags: - ECMAScript 2015 - JavaScript - Math - Method - Reference translation_of: Web/JavaScript/Reference/Global_Objects/Math/clz32 ---
Math.clz32()
関数は、引数として与えられた数値の 32 ビットバイナリ表現での先頭の 0 の個数を返します。
Math.clz32(x)
x
与えられた数値の32ビットバイナリ表現での先頭の 0 の個数。
"clz32
" は CountLeadingZeroes32 の省略形です。
x
が数値でない場合、まず数値に変換され、32ビット符号なし整数値に変換されます。
変換された 32 ビット符号なし整数値が 0
の場合、すべてのビットが 0
であるため、32
を返します。
この関数は Emscripten のような JS にコンパイルするシステムに対して特に役に立ちます。
現在のところ、 "Count Leading Ones" を表す Math.clon
はありません ("clo" ではなく "clon" と名付けられています、なぜなら "clo" と "clz" は特に英語を話さない人にとっては似すぎているからです)。しかし、 clon
関数は、数値のビットを逆数にして、その結果を Math.clz32
に渡すことで簡単に作ることができます。 1 の逆数は 0 であり、その逆も同様です。このように、ビットを逆数にすると、測定された 0 の量が (Math.clz32
からの) 逆数になり、 Math.clz32
はゼロの数を数えるのではなく、1 の数を数えるようになります。
以下の32ビットワード値を想定してみます。
var a = 32776; // 00000000000000001000000000001000 (16 leading zeros) Math.clz32(a); // 16 var b = ~32776; // 11111111111111110111111111110111 (32776 inversed, 0 leading zeros) Math.clz32(b); // 0 (this is equal to how many leading one's there are in a)
この論理を使用すると、 clon
関数は次のように作成することができます。
var clz = Math.clz32; function clon(integer){ return clz(~integer); }
さらに、この技術を拡張して、以下に示すようなジャンプレスの「Count Trailing Zeros」と「Count Trailing Ones」関数を作成することができます。以下の ctrz
関数は、すべての上位ビットを最も低いビットで埋め、そのビットを否定して上位のセットビットをすべて消去するので、clz が使用できます。
var clz = Math.clz32; function ctrz(integer){ // count trailing zeros // 1. fill in all the higher bits after the first one integer |= integer << 16; integer |= integer << 8; integer |= integer << 4; integer |= integer << 2; integer |= integer << 1; // 2. Now, inversing the bits reveals the lowest bits return 32 - clz(~integer) |0; // `|0` ensures integer coercion } function ctron(integer){ // count trailing ones // No shift-filling-in-with-ones operator is available in // JavaScript, so the below code is the fastest return ctrz(~integer); /* Alternate implementation for demonstrational purposes: // 1. erase all the higher bits after the first zero integer &= (integer << 16) | 0xffff; integer &= (integer << 8 ) | 0x00ff; integer &= (integer << 4 ) | 0x000f; integer &= (integer << 2 ) | 0x0003; integer &= (integer << 1 ) | 0x0001; // 2. Now, inversing the bits reveals the lowest zeros return 32 - clon(~integer) |0; */ }
これらのヘルパー関数を ASM.JS モジュールに入れます。そして、そうすれば、真のパフォーマンスの傑作ができあがります。このような状況は、まさに ASM.JS のために設計されたものです。
var countTrailsMethods = (function(stdlib, foreign, heap) { "use asm"; var clz = stdlib.Math.clz32; function ctrz(integer) { // count trailing zeros integer = integer | 0; // coerce to an integer // 1. fill in all the higher bits after the first one // ASMjs for some reason does not allow ^=,&=, or |= integer = integer | (integer << 16); integer = integer | (integer << 8); integer = integer | (integer << 4); integer = integer | (integer << 2); integer = integer | (integer << 1); // 2. Now, inversing the bits reveals the lowest bits return 32 - clz(~integer) |0; } function ctron(integer) { // count trailing ones integer = integer | 0; // coerce to an integer return ctrz(~integer) |0; } // unfourtunately, ASM.JS demands slow crummy objects: return {a: ctrz, b: ctron}; })(window, null, null); var ctrz = countTrailsMethods.a; var ctron = countTrailsMethods.b;
Math.clz32(1); // 31 Math.clz32(1000); // 22 Math.clz32(); // 32 var stuff = [NaN, Infinity, -Infinity, 0, -0, false, null, undefined, 'foo', {}, []]; stuff.every(n => Math.clz32(n) == 32); // true Math.clz32(true); // 31 Math.clz32(3.5); // 30
以下のポリフィルが最も効果的です。
if (!Math.clz32) Math.clz32 = (function(log, LN2){ return function(x) { // Let n be ToUint32(x). // Let p be the number of leading zero bits in // the 32-bit binary representation of n. // Return p. var asUint = x >>> 0; if (asUint === 0) { return 32; } return 31 - (log(asUint) / LN2 | 0) |0; // the "| 0" acts like math.floor }; })(Math.log, Math.LN2);
仕様書 |
---|
{{SpecName('ESDraft', '#sec-math.clz32', 'Math.clz32')}} |
{{Compat("javascript.builtins.Math.clz32")}}