javascript 位运算
位运算博大精深,本文总结下基本的位运算的概念。
1、整数的二进制码
位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以IEEE-754 64位格式存储,但位操作符并不直接操作64位的值。而是先将64位的值转换成32位的整数,然后执行操作,最后再将结果转换回64位。对于开发人员来说,由于64位存储格式是透明的,因此整个过程就像是只存在32位的整数一样。
对于有符号的整数,32位中的前31位用于表示整数的值。第32位用于表示数值的符号:0表示正数,1表示负数。这个表示符号的位叫做符号位。例如,数值18的二进制表示是00000000000000000000000000010010,或者更简洁的10010。
负数同样以二进制码存储,但使用的是二进制补码(其实正数也是用补码表示)。计算一个数值的二进制补码,需要经过下列三个步骤:
- 求这个数值绝对值的二进制码
- 求二进制反码,即将0替换为1,将1替换为0
- 得到的二进制反码加1
比如求-18的二进制码,首先求得18的二进制码:
0000 0000 0000 0000 0000 0001 0010
然后求其二进制反码:
1111 1111 1111 1111 1111 1110 1101
最后,二进制反码+1
1111 1111 1111 1111 1111 1110 1110
这样就求得了-18的二进制表示。
在ECMAScript中,当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换成32位数值,然后执行位操作,最后再将32位的结果转换回64位数值。这样,表面上看起来就好像是在操作32位数值。但这个转换过程也导致了一个严重的负效应,即在对特殊的NaN和Infinity值应用位操作时,这两个值都会被当成0来处理。如果对非数值进行位操作,会先使用Number()函数将该数值转换成一个数值(自动完成),然后再应用位操作,得到的结果是一个数值。
2、~ & | ^
接下来介绍4个位操作符。
按位非操作符由一个波浪线(~)表示,执行按位非的结果就是返回数值的反码。
var num = 25;
console.log(~num); // -26
对25执行按位非操作,结果得到了-26,这也验证了之前说的结论,“一个负数的二进制码是该数绝对值的反码+1”
按位与操作符由一个和号字符(&)表示,它有两个操作符数,按位与操作只在两个数值的对应位都是1时才返回1,否则0。
按位或操作符由一个竖线符号(|)表示,同样也有两个操作符,在有一位是1的情况下返回1,否则0.
按位异或操作符由一个插入符号(^)表示,在两个数值对应位上只有一个1时返回1,否则0。
3、<< >> >>>
左移符号由两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数。在左移后,原数值右侧空出的位由0填补。
左移一位其实就相当于将原数值乘以2,左移不会影响操作数的符号位。
右移操作符由两个大于号(>>)表示,这个操作符会将数值向右移动,但保留符号位。在移位过程中,空缺位出现在原数值的左侧,符号位的右侧,用符号位的值来填充空位。右移一位相当于原数除2后向下取整。
无符号右移操作符由三个大于号(>>>)表示,这个操作符会将数值的所有32位都向右移动。对正数来说,无符号右移的结果和有符号相同,但是对负数来说就不一样了,无符号右移会把负数的符号位也进行移动,左边空出位置用0填充。
var num = -64;
console.log(num >> 5); // -2
console.log(num >>> 5); // 134217726
对-64进行无符号右移操作,将其用二进制码表示:
1111 1111 1111 1111 1111 1111 1100 0000
右移5位后:
0000 0111 1111 1111 1111 1111 1111 1110
即十进制的134217726。
notice:并没有无符号左移!
4、关于位运算的坑
了解的基本的位运算操作后,这里我要谈谈我经常碰到的一个坑。
int32的取值范围是-2^31 ~ 2^31-1,于是我经常会去求1<<31的值,但是是溢出的...
console.log(1 << 31); // -2147483648
原因很简单,1的左边只有30位可以移动,实际上把1移到了符号位上,得到了:
1000 0000 0000 0000 0000 0000 0000 0000
所以要表示int32的区间范围,可以这样:
console.log(1 << 31); // -2147483648
console.log(1 << -1); // -2147483648
console.log(-0x80000000); // -2147483648
console.log(~(1 << 31)); // 2147483647
console.log(-(1 << -1) - 1); // 2147483647
console.log(0x7fffffff); // 2147483647
console.log(Math.pow(2, 31) - 1); // 2147483647
console.log((1 << 30) * 2 - 1); // 2147483647
javascript 位运算的更多相关文章
- JavaScript 位运算总结&拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...
- javascript位运算
javascript作为一门高级语言,他尽量让开发人员减少思考底层的硬件工作原理,而将精力集中在逻辑开发的层面.不过,不论这门语言多么高级,我们必须知道数据依然以bits的形式存储,有时候我们会直接与 ...
- leetcode - 位运算题目汇总(下)
接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目. Bitwise AND of Numbers Range 给出一个范围,[m, ...
- 位运算总结&拾遗
JavaScript 位运算总结&拾遗 最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识 ...
- javascript的变态位运算
javascript的变态位运算 var a = "10" | 0; alert(a); alert (typeof a);结果为10,number. 这就是说这条语句可以将字符串 ...
- 【JavaScript】进制转换&位运算,了解一下?
前言 在一般的代码中很少会接触到进制和位运算,但这不代表我们可以不去学习它.作为一位编程人员,这些都是基础知识.如果你没有学过这方面的知识,也不要慌,接下来的知识并不会很难.本文你将会学习到: 进制转 ...
- javascript中的类型转换(进制转换|位运算)
1:parseInt(string) : 这个函数的功能是从string的开头开始解析,返回一个整数 parseInt("123hua"); //输出 123 parseInt(& ...
- javascript中的位运算,
罗浮宫群里又有讨论位运算符号|了,做过一段时间php,数据库保存布尔值数据经常用到,比如100110 就表明了六个属性的是与否,极大减少了数据量..] ECMAScript 中位运算跟其他语言一样的. ...
- js中的位运算
按位运算符是把操作数看作一系列单独的位,而不是一个数字值.所以在这之前,不得不提到什么是"位": 数值或字符在内存内都是被存储为0和 1的序列,每个0和1被称之为1个位,比如说10 ...
随机推荐
- Java Se : Java NIO(服务端)与BIO(客户端)通信
Java目前有三种IO相关的API了,下面简单的说一下: BIO,阻塞IO,最常用的Java IO API,提供一般的流的读写功能.相信学习Java的人,都用过. NIO,非阻塞IO,在JDK1.4中 ...
- coursera机器学习笔记-神经网络,学习篇
#对coursera上Andrew Ng老师开的机器学习课程的笔记和心得: #注:此笔记是我自己认为本节课里比较重要.难理解或容易忘记的内容并做了些补充,并非是课堂详细笔记和要点: #标记为<补 ...
- 【hadoop】——window下elicpse连接hadoop集群基础超详细版
1.Hadoop开发环境简介 1.1 Hadoop集群简介 Java版本:jdk-6u31-linux-i586.bin Linux系统:CentOS6.0 Hadoop版本:hadoop-1.0.0 ...
- javax.servlet.ServletException cannot be resolved to a type错误解决方法
在页面中使用全局路径时${pageContext.request.contextPath}出现javax.servlet.ServletException cannot be resolved to ...
- 烂泥:mysql5.5多实例部署
本文由秀依林枫提供友情赞助,首发于烂泥行天下. mysql5.5数据库多实例部署,我们可以分以下几个步骤来完成. 1. mysql多实例的原理 2. mysql多实例的特点 3. mysql多实例应用 ...
- Navicat for MySQL 工具注册码
在使用 MySQL 客户端中,感觉 Navicat for MySQL 做的还是很不错的.鄙人比较懒,喜欢采用绿色安装的方式,百度网盘上备份的有个绿色的压缩包,解压打开需要注册,这里记录一下注册码,版 ...
- Linux磁盘管理之元数据、文件和目录、链接文件03
一.存储设备分区简述 文件系统最终目的是把大量数据有组织的放入持久性的存储设备,如硬盘.硬盘存储能力具有持久性,不会因为断电而消失,存储量大,但读取速度慢.操作系统读取硬盘的时候,不会一个一个扇区读取 ...
- 理解linux and inode
inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统操作水平,还有助于体会Unix设计哲学,即如何把底层的复杂性抽象成一个简单概念 ...
- java报表工具FineReport的SQL编辑框的语法简介
感谢大家捧场,这里继续分享关于SQL编辑框的一些语法心得总结,因为数据集定义的面板,也是FineReport报表中最常用的模块之一. 1.我理解的执行过程. 这里其实是生成一个字符串,FineRepo ...
- 理解 OpenStack Swift (1):OpenStack + 三节点Swift 集群+ HAProxy + UCARP 安装和配置
本系列文章着重学习和研究OpenStack Swift,包括环境搭建.原理.架构.监控和性能等. (1)OpenStack + 三节点Swift 集群+ HAProxy + UCARP 安装和配置 ( ...