From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../reference/global_objects/math/clz32/index.html | 169 +++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 files/zh-cn/web/javascript/reference/global_objects/math/clz32/index.html (limited to 'files/zh-cn/web/javascript/reference/global_objects/math/clz32') diff --git a/files/zh-cn/web/javascript/reference/global_objects/math/clz32/index.html b/files/zh-cn/web/javascript/reference/global_objects/math/clz32/index.html new file mode 100644 index 0000000000..76501c5be5 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/math/clz32/index.html @@ -0,0 +1,169 @@ +--- +title: Math.clz32() +slug: Web/JavaScript/Reference/Global_Objects/Math/clz32 +translation_of: Web/JavaScript/Reference/Global_Objects/Math/clz32 +--- +
{{JSRef("Global_Objects", "Math")}}
+ +

概述

+ +

Math.clz32() 函数返回一个数字在转换成 32 无符号整形数字的二进制形式后, 开头的 0 的个数, 比如 1000000 转换成 32 位无符号整形数字的二进制形式后是 00000000000011110100001001000000, 开头的 0 的个数是 12 个, 则 Math.clz32(1000000) 返回 12.

+ +

语法

+ +
Math.clz32 (x)
+
+ +

参数

+ +
+
x
+
一个数字.
+
+ +

描述

+ +

"clz32" 是 CountLeadingZeroes32 的缩写.

+ +

如果 x 不是数字类型, 则它首先会被转换成数字类型, 然后再转成 32 位无符号整形数字. 

+ +

如果转换后的 32 位无符号整形数字是 0, 则返回 32, 因为此时所有位上都是 0.

+ +

NaN, Infinity, -Infinity 这三个数字转成 32 位无符号整形数字后都是 0.

+ +

这个函数主要用于那些编译目标为 JS 语言的系统中, 比如 Emscripten.

+ +

示例

+ +
Math.clz32(1)                // 31
+Math.clz32(1000)             // 22
+Math.clz32()                 // 32
+[NaN, Infinity, -Infinity, 0, -0, null, undefined, "foo", {}, []].filter(function (n) {
+  return Math.clz32(n) !== 32
+})                           // []
+Math.clz32(true)             // 31
+Math.clz32(3.5)              // 30
+
+ +

计算前导1的个数

+ +

目前javascript尚未提供Math.clon函数来计算前导1的个数(之所以叫“clon”而非“clo”,是因为“clo”与“clz”太过相似,特别对那些母语不是英语的人来说),但是你可以通过将一个数取反并将其作为Math.clz32的参数来实现clon函数。其中的原理非常简单,因为对1取反是0,反之亦然,所以用Math.clz32计算前导0的个数就变成计算前导1的个数。

+ +

先看以下代码:

+ +
var a = 32776;   // 00000000000000001000000000001000 (16个前导0)
+Math.clz32(a);   // 16
+
+var b = ~32776;  // 11111111111111110111111111110111 (对32776取反, 0个前导0)
+Math.clz32(b);   // 0 (相当于0个前导1)
+ +

通过以上方法,clon 函数可以定义如下:

+ +
var clz = Math.clz32;
+function clon(integer){
+    return clz(~integer);
+}
+ +

现在,我们可以进一步实现计算“尾随0”和“尾随1”的个数了。下面的ctrz函数将第一个1之后的高数位全部置为1然后取反,再用Math.clz32求得尾随0的个数。

+ +
var clz = Math.clz32;
+function ctrz(integer){ // 计算尾随0个数
+    // 1. 将第一个1之后的高数位全部置为1
+    // 00000000000000001000000000001000 => 11111111111111111111111111111000
+    integer |= integer << 16;
+    integer |= integer << 8;
+    integer |= integer << 4;
+    integer |= integer << 2;
+    integer |= integer << 1;
+    // 2. 然后,对该数取反,此时低位的1的个数即为所求
+    return 32 - clz(~integer) |0; // `|0`用于保证结果为整数
+}
+function ctron(integer){ // 计算尾随1个数
+    // JavaScript中没有移位补1的运算符
+    // 所以下面的代码是最快的
+    return ctrz(~integer);
+    /* 为了看起来比较对称,你也可以使用以下代码:
+       // 1. 将第一个0之后的高数位全部置为0
+       integer &= (integer << 16) | 0xffff;
+       integer &= (integer << 8 ) | 0x00ff;
+       integer &= (integer << 4 ) | 0x000f;
+       integer &= (integer << 2 ) | 0x0003;
+       integer &= (integer << 1 ) | 0x0001;
+       // 2. 然后,对该数取反,此时低位的0的个数即为所求
+       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) { // 计算尾随0个数
+        integer = integer | 0; // 确保是整数
+        // 1. 将第一个1之后的高数位全部置为1
+        // ASMjs中不允许^=、&=、和|=
+        integer = integer | (integer << 16);
+        integer = integer | (integer << 8);
+        integer = integer | (integer << 4);
+        integer = integer | (integer << 2);
+        integer = integer | (integer << 1);
+        // 2. 然后,对该数取反,此时低位的1的个数即为所求
+        return 32 - clz(~integer) |0;
+    }
+    function ctron(integer) { // 计算尾随1个数
+        integer = integer | 0; // 确保是整数
+        return ctrz(~integer) |0;
+    }
+    // 蛋疼的是,ASM.JS必须使用糟糕的object类型:
+    // unfourtunately, ASM.JS demands slow crummy objects:
+    return {a: ctrz, b: ctron};
+})(window, null, null);
+var ctrz = countTrailsMethods.a;
+var ctron = countTrailsMethods.b;
+ +

Polyfill

+ +

这个polyfill效率最高。

+ +
if (!Math.clz32) Math.clz32 = (function(log, LN2){
+  return function(x) {
+    var asUint = x >>> 0; // 将x转换为Uint32类型
+    if (asUint === 0) {
+      return 32;
+    }
+    return 31 - (log(asUint) / LN2 | 0) |0; // "| 0"相当于Math.floor
+  };
+})(Math.log, Math.LN2);
+ +

规范

+ + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ES6', '#sec-Math.clz32', 'Math.clz32')}}{{Spec2('ES6')}}Initial definition.
+ +

浏览器兼容性

+ + + +

{{Compat("javascript.builtins.Math.clz32")}}

+ +

相关链接

+ + -- cgit v1.2.3-54-g00ecf