javascript 中的二进制运算的一些技巧,晒出来和你们分享一下,希望可以帮助你们

1、原码、反码、补码,正数减法转补码加法 
js
在进行二进制运算时,使用 32 位二进制整数,由于 js 的整数都是有符号数,最高位0表示正数,1表示负数,因此,js
二进制运算中使用的整数表达范围是

复制代码代码如下:

-Math.pow(2,31) ~ Math.pow(2,31)-1 //
-2147483648 ~ 2147483647 

原码:最高位 0 表示正,1表示负,其余 31
位是该数的绝对值(真值的绝对值)的二进制形式 
反码:正数反码与原码相同,负数反码是原码符号位不变,其余31位取反(0变1,1变0) 
补码:正数补码与原码相同,负数补码为反码加 1
(符号位参与运算,其实只有求 -0 的补码才涉及最高位进位,因此不用担心在反码加1时由于符号位参与运算进位而使 - 变 +)。 
+0
的反码:32个0 ,按正数处理,原码、反码、补码都是0。 
-0 的反码:最高位1,其余位由 +0 原码取反,得到 32 个

-0 的补码:其反码是 32 个 1 加
1,最高位溢出被舍弃,得到 32 个0 
因此,正负 0
的补码都是 0. 
由负数的补码求他的绝对值补码:负二进制数的绝对值,只要各位(包括符号位)取反,再加1,就得到其绝对值。 
计算机在处理加减运算时,使用补码进行运算,减法被视为加上一个负数,在处理负数时,用负数的补码进行加法可以即可得到正确运算结果,补码是为了统一加减运算而生的。 
正数减法转补码加法的原理是 32 位数溢出: 
对于32 位二进制正整数来说,其模为

复制代码代码如下:

Math.pow(2,32) = 4294967296 

32
位正整数最大表达范围是 4294967296 - 1 ,达到 4294967296 这个值就要进位到33位,33 位是溢出位被丢弃,只得到32
个0(这个道理跟表盘上 0 点 和12 点的时针指在同一个位置是一样的,表盘以 12 为模),因此,一个数逐渐增大,一旦超出 4294967296-1 的数 M
就可以表示为 M%4294967296 
而负数 -M
(M为绝对值)可以表示为一个正数: 4294967296 - M(这个正数就是负数的补码对应的二进制正整数,负数的补码按32位二进制数,与他的原码相加刚好等于模
),道理跟表盘一样,11点和负1点指在同一个位置。 

-3 为例:

复制代码代码如下:

(Array(32).join("0")+(3).toString(2)).slice(-32); // |-3|
的二进制数,即原码 
原码 =
00000000000000000000000000000011; 
反码 =
11111111111111111111111111111100; //原码符号位为1,其余位取反 
补码
= 11111111111111111111111111111101;
//反码加1因为反码由正数形式的原码低31位取反得到,因此这两个数的低31位全都是1,加上反码符号位1,得到32 个1 
那么,有 
补码+原码 = (反码+1)+原码 
=
(反码+原码)+1 
= 1+(32位全是 1
的二进制数) //因为反码由正数形式的原码的低31位取反加上符号位1得到,因此这两个数的和的低31位全都是1,加上反码符号位1,得到32 个1 
= Math.pow(2,32) 
=
4294967296 //这正是32位二进制数的模, 跟 |-1|+11 = 12 原理一样 

这就是:
正数减法 -> 负数加法 -> 补码加法 的过程。 
2、位运算 
因为 js 的整数默认是带符号正数,所以在为运算中,只能使用 31
位,开发者是不能访问最高位的。 
位运算只发生在整数上,因此一个非浮点数参与位运算之前会被向下取整。 
为了避免访问符号位, javascript 在现实 负数的
二进制时,转换为 符号及 其绝对值的二进制,如:

复制代码代码如下:

(-123).toString(2) ;// "-1111011" 

按位取反(~): 一元运算, 1 变0,0变1
,如 
~123 ; //-124 
可以验证一下这个过程:正数取反,符号位为负,所以结果是一个负数,根据
Math.pow(2,32) - M 可以表示成 -M,可以按下面方法计算

复制代码代码如下:

parseInt((Array(32).join(0)+
(123).toString(2)).slice(-32).replace(/\d/g,function(v) { 
return
(v*1+1)%2; 
}),2)-Math.pow(2,32) // -124
,如果是负数减 Math.pow(2,32) 

需要注意的是, javascript
位运算都是有符号的,因此达到 32 位,其最高位将作为 符号位,取反时应得到正数(取模 Math.pow(2,32)
的补数--两个数相加得到模,称这两个数互为补数)。 
对整数 M 按位取反可以这样算:

复制代码代码如下:

((-1*M-1)+Math.pow(2,32))%Math.pow(2,32) 

按位与(&):两个数的相同位,都是 1 返回1
,否则返回0

复制代码代码如下:

&234 = 106 
"00000000000000000000000001111011" 
"00000000000000000000000011101010" 
--------------------------------------------- 
"00000000000000000000000001101010"

复制代码代码如下:

|234 = 251 
"00000000000000000000000001111011" 
"00000000000000000000000011101010" 
--------------------------------------------- 
"00000000000000000000000011111011" 

按位异或(^):两个数的相同位,一个是 1 另一个是
0 则返回 1,否则返回0

复制代码代码如下:

^234 = 145 
"00000000000000000000000001111011" 
"00000000000000000000000011101010" 
--------------------------------------------- 
"00000000000000000000000010010001" 

异或运算的一些特性:

复制代码代码如下:

a ^ a = 0   
a
^ b = b ^ a   
a ^ b ^ c = a
^ (b ^ c) = (a ^ b) ^ c 
a ^
b ^ a = b 
d = a ^ b ^ c 可以推出
a = d ^ b ^ c //这个特性被用在一些加密算法中 
//如果运算数在适当范围内(不溢出), 如
a=1,b=2,交换两个变量的值 
a =
[b,b=a][0] 
//或者 
a
= a^b 
b = a^b 
a=
a^b 

利用位的异或运算使用一个数字记录多个信息: 
有几个状态值分别是 1、2、8、16 ..... 
这些值的规律是,他们的二进制只有一位是 1 ,其余都是 0,
因此, 他们中的任意几个的按位异或运算的结果都不会出现 两个数的某一位都是 1
的情况,并且运算的值都是唯一确定的,也就是,知道运算的结果,就知道是哪几个数的组合,这样可以用一个数字记录多个信息。

复制代码代码如下:

00000001 
00000010 
00000100 
00001000 
00010000 

1^2^4 = 7 //
"00000111" 
因此,如果我们知道结果是 7
,就知道他们是由 1 、2、4 组合而成。 
如果我们要设置一个参数,使其包含几个状态值,就可以用
按位或运算, 
这样的例子可以参考 PHP
中关于图片类型的几个常量,和 PHP 错误等级定义的几个常量。 
这样的例子,也许有用十进制数来描述的,比如:
个位数的数字表示某个属性的状态,十位数的数字表示另一个属性的状态,这样的话,每个状态可以有 10 个值,只用一个数字就可以描述的组合非常多。 
左移位(<<) :
一个数的二进制所有位向左移动,符号位不动,高位溢出丢弃,低位补 0 
如果不溢出, 左移位的效果是乘以 2。 
右移位(>>):
一个数的二进制所有位向右移动,符号位不动,高位补0,低位丢弃 
右移位操作的效果是除以 2 并向下取整。 
带符号右移(>>>):移位时符号位跟随移动,符号位也作为数值看待,所以,该操作的结果是
32 位无符号整数,因此负数的带符号右移将产生正整数,正数的带符号右移与 无符号右移相同,这是唯一可以操作符号位的运算。 
-123>>>1
;//2147483586 
一些要注意的地方: 
位运算必须是整数,如果运算元不是可用的整数,将取 0
作为运算元

复制代码代码如下:

~NaN; // 将执行 ~0 ,结果为 -1 
~‘x‘;
// -1 
‘hello‘|0; // 0 
({})|0 ; //0 

位移运算不能移动超过31位,如果试图移动超过31位,将位数
对32取模后再移位 
123>>32
//实际是 123>>0 (32%32 = 0) 
123>>33 //实际是
123>>1 
32位带符号整数表达范围是
-Math.pow(2,31) ~ Math.pow(2,31)-1 即 -2147483648~2147483647,而 js
数字的精度是双精度,64位,如果一个超过 2147483647
的整数参与位运算的时候就需要注意,其二进制溢出了,截取32位后,如果第32位是1将被解读为负数(补码)。

复制代码代码如下:

>>0; //-2147483648 
>>0;
//0 
>>0; //-1 
>>0; //1

javascript 中的二进制运算的一些技巧,晒出来和你们分享一下,希望可以帮助你们,布布扣,bubuko.com

时间: 2024-10-21 07:42:07

javascript 中的二进制运算的一些技巧,晒出来和你们分享一下,希望可以帮助你们的相关文章

Javascript中最常用的经典技巧

1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table border oncontextmenu=return(false)><td>no</table> 可用于Table 2. <body onselectstart="return false"> 取消选取.防止复制 3. onpaste="return false" 不

JavaScript中的try...catch和异常处理

在JavaScript可以使用try...catch来进行异常处理.例如: try { foo.bar();} catch (e) { alert(e.name + ": " + e.message);} 目前我们可能得到的系统异常主要包含以下6种: EvalError: raised when an error occurs executing code in eval() RangeError: raised when a numeric variable or parameter

【前端】javascript中10常用的个小技巧总结

javascript中10常用的个小技巧总结 本文转自:http://www.cnblogs.com/libin-1/p/6756393.html 1. new Set() 可能有人知道ES6中提供了新的数据结构 Set,但是能够灵活运用的人或许不多.利用Set数据结构我们能够轻松的去重一个数组,比如: let arr = [1, 2, 2, 3]; let set = new Set(arr); let newArr = Array.from(set); // Array.from方法可以将

javascript中关于&amp;&amp; 和 || 表达式的小技巧分享

如果你还是新手, 而且读完所有这些技巧的详解和每种技巧是如果工作的以后运用它们, 你会写出更加简练高效的JavaScript程序. 确实, JavaScript高手已经运用这些技巧写出了很多强大, 高效的JavaScript程序. 但是你可以这样. 强大的 && 和 || 表达式你可能在JavaScript库和JavaScript框架中已经见过它们了, 那么我们先由几个基本的例子开始: 例子1. || (或)设置默认值, 通常用 代码如下: 1 function documentTitle

一些JavaScript中的DOM的优化小技巧

在进行DOM优化时需要关注的问题有:修改DOM的时候,会引起页面的重排,重绘.因为JS是单线程执行的,那么在重排重绘的过程中可能会阻塞用户的操作.为了更好的用户体验,必须要严格控制这些操作. 一.对象集合 NodeList 当我们调用:getElementsByTagName,getElementsByName,getElementsByClassName的时候,返回的结果是一个NodeList,这个NodeList是实时的.如果你修改对应的html,那么NodeList中也会得到修改. 而且,

javascript中查看元素事件函数的一些技巧

在分析一些网页的时候,经常会发现点击某个按钮会触发某个动作,当页面比较复杂,包含的js文件又多,这时候要找到这段触发函数的代码写在哪里就比较困难.比如,在某个html页面中,发现如下一个按钮,点击后会使得页面元素有变化.但是并未看到onclick事件,那说明该事件可能是通过javascript中的addEventListener方法绑定的(IE不支持该方法,使用的是attachEvent,不理解为微软何非要和W3C标准对着干).例如下面的代码: <input type="button&qu

【转】深入浅出 JavaScript 中的 this

Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象.一般在编译期确定下来,或称为编译期绑定.而在 JavaScript 中,this 是动态绑定,或称为运行期绑定的,这就导致 JavaScript 中的 this 关键字有能力具备多重含义,带来灵活性的同时,也为初学者带来不少困惑.本文仅就这一问题展开讨论,阅罢本文,读者若能正确回答 JavaScript 中的 What ’s this 问题,作为作者,我就会觉得花费这么多功夫,撰写这样一篇文章是值得的. Java

Javascript中this关键字详解

原文出处:http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_this_in_javascript.html Quiz 请看下面的代码,最后alert出来的是什么呢? 1 var name = "Bob"; 2 var nameObj ={ 3 name : "Tom", 4 showName : function(){ 5 alert(this.name); 6 }, 7 waitShowNa

JavaScript 中对变量和函数声明的提前示例

如题所示,看下面的示例(可以使用Chrome浏览器,然后F12/或者右键,审查元素.调出开发者工具,进入控制台console输入)(使用技巧: 控制台输入时Shift+Enter可以中途代码换行) var name = "xiaoming"; (function(){ var name = name || "小张"; console.info(name); })();// 小张 (function(){ name = name || "小张";