位运算总结&拾遗
JavaScript 位运算总结&拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识。
把一个数变为大于等于该数的最小的2的幂
一个数为2的幂,那么该数的二进制码只有最高位是1。
根据这个性质,我们来举个栗子,比如有数字10,转为二进制码后为:
1 0 1 0
我们只需把 0 bit的位置全部用1填充,然后再把该二进制码加1就ok了。而x | (x + 1)正好可以把最右边的0置为1,可是问题来了,当二进制码变成 1 1 1 1后,我们无法判断二进制码已经全是1了,继续操作的话会变成1 1 1 1 1,于是,该法失败...
我们可以采用类似迭代的方法,又有点分组的意思。因为最高位肯定是1,我们把init的数右移一位,和原数作与运算,这样就能把次高位也置为1,然后继续右移,这时最前面两位都是1了,右移两位后,做与运算,这时前四位都是1了:
function change2Pow(n) {
if(!(n & (n-1)) && n > 0) return n;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return n + 1;
}
计算二进制中1的个数
leetcode中有一道这样的题目-Number of 1 Bits,正好拿来验证程序的正确性。
常规解法不用多说,直接上代码:
var hammingWeight = function(n) {
var ans = 0;
while (n) {
ans += n & 1;
n >>>= 1;
}
return ans;
};
因为题目中有说是unsigned int32的整数,所以要用有符号右移>>>来操作符号位。
位运算解法和求逆序一样,也采用分组的思想。
我们以16位下的12345举例(6个1),先写出它的二进制码表示:
0011000000111001
第一步:每两个为一组,组内高低位相加
00 10 00 00 00 10 01 01
第二步:每四个为一组,组内高低位相加
0010 0000 0010 0010
第三步:每8个为一组,组内高低位相加
00000010 00000100
第四步,每16个为1组,组内高低位相加
0000000000000110
最后得到的数字6即为12345二进制码中1的个数。而实际中,因为int32是32位的,所以一共要进行5步。求解思路和求逆序类似,逆序是要交换,所以要分别左移右移,而求1的个数是相加,所以只需移动一次就够了。
完整代码:
var hammingWeight = function(n) {
n = ((n & 0xAAAAAAAA) >>> 1) + (n & 0x55555555);
n = ((n & 0xCCCCCCCC) >>> 2) + (n & 0x33333333);
n = ((n & 0xF0F0F0F0) >>> 4) + (n & 0x0F0F0F0F);
n = ((n & 0xFF00FF00) >>> 8) + (n & 0x00FF00FF);
n = ((n & 0xFFFF0000) >>> 16) + (n & 0x0000FFFF);
return n;
};
因为是unsigned int32,所以要用>>>如前所述。
再次击败100%的JavaScript code...
计算二进制中1的个数的奇偶性
我们可以先计算1的个数,然后再判断奇偶。当然既然作为一道独立的题目,肯定有更简便的方法。
整个过程可以用分治来解。第1步统计相邻2位的1的个数奇偶性,保存到这2位的低位中。第2步统计相邻4位的1的个数奇偶性,保存到这4位的低位中。……第5步统计相邻2位的1的个数奇偶性,保存到这32位的低位中,即x的最低位。
function bit1OddEven(x){ //奇数个为1,偶数个为0
x ^= x >>> 1; //相邻 2位中1的奇偶性
x ^= x >>> 2; //相邻 4位中1的奇偶性
x ^= x >>> 4; //相邻 8位中1的奇偶性
x ^= x >>> 8; //相邻16位中1的奇偶性
x ^= x >>> 16; //相邻32位中1的奇偶性
return x & 1;
}
统计二进制前导0、末尾0的个数
先排除为0的特殊情况。然后先看前16位是否全0,如果全0,增加计数,并把这个数左移16位删除已经计数的16个0。然后看前8位是否全0。一直到只剩一位时可以直接计算。整个过程的核心是二分思想。
统计末尾0的个数时思想类似,只是变成了统计后面16位、8位等是否全0。
function countLeading0(x) {
if (!x) return 32;
var n = 1;
if ((x >>> 16) == 0) n += 16, x <<= 16;
if ((x >>> 24) == 0) n += 8, x <<= 8;
if ((x >>> 28) == 0) n += 4, x <<= 4;
if ((x >>> 30) == 0) n += 2, x <<= 2;
return n - (x >>> 31);
}
function countTrailing0(x) {
if (!x) return 32;
var n = 1;
if ((x << 16) == 0) n += 16, x >>>= 16;
if ((x << 24) == 0) n += 8, x >>>= 8;
if ((x << 28) == 0) n += 4, x >>>= 4;
if ((x << 30) == 0) n += 2, x >>>= 2;
return n - (x & 0x01);
}
当然计算末尾0的个数,我们也可以这样:
function countTrailing0(a) {
return Math.log(a & (-a)) / Math.LN2;
}
这个系列暂时结束了,但我知道对于位运算的学习,这只是起点。
附位运算系列目录:
位运算总结&拾遗的更多相关文章
- JavaScript 位运算总结&拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...
- leetcode - 位运算题目汇总(下)
接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目. Bitwise AND of Numbers Range 给出一个范围,[m, ...
- Java 位运算2-LeetCode 201 Bitwise AND of Numbers Range
在Java位运算总结-leetcode题目博文中总结了Java提供的按位运算操作符,今天又碰到LeetCode中一道按位操作的题目 Given a range [m, n] where 0 <= ...
- 简简单单学会C#位运算
一.理解位运算 要学会位运算,首先要清楚什么是位运算?程序中的所有内容在计算机内存中都是以二进制的形式储存的(即:0或1),位运算就是直接对在内存中的二进制数的每位进行运算操作 二.理解数字进制 上面 ...
- SQL Server时间粒度系列----第8节位运算以及设置日历数据表节假日标志详解
本文目录列表: 1.位运算 2.设置日历数据表节假日标志 3.总结语 4.参考清单列表 位运算 SQL Server支持的按位运算符有三个,分别为:按位与(&).按位或(|).按位异或 ...
- js中的位运算
按位运算符是把操作数看作一系列单独的位,而不是一个数字值.所以在这之前,不得不提到什么是"位": 数值或字符在内存内都是被存储为0和 1的序列,每个0和1被称之为1个位,比如说10 ...
- Java中的位运算
昨天去面试的时候做到了一道Java的位运算题目,发现有个运算符不懂:">>>",今天特地查了一下,并小结一下常见的位运算符号: ~ 按位非(NOT)(一元运算) ...
- C#位运算讲解与示例
首先每一个权限数都是2的N次方数 如:k1=2 ; //添加 k2=4 ; //删除 k3=8; //修改 ... 如此定义功能权限数,当需要组合权限时,就需要对各个所拥有的权限数按位或了. 如: p ...
- C#枚举中的位运算权限分配浅谈
常用的位运算主要有与(&), 或(|)和非(~), 比如: 1 & 0 = 0, 1 | 0 = 1, ~1 = 0 在设计权限时, 我们可以把权限管理操作转换为C#位运算来处理. 第 ...
随机推荐
- Android定位功能
不说废话,直接说说实现android定位有关的API吧. 这些API都在android.location包下,一共有三个接口和八个类.它们配合使用即可实现定位功能. 三个接口: GpsStatus.L ...
- 添加xml文件编辑语法提示
找到Struts的lib目录 找到struts2-core-文件并解压开 这个struts.dtd文件才是我们需要添加的文件 双击XML Catalog 点击ADD Key中复制粘贴D:\web\st ...
- DateTime.Compare(t1,t2)比較两个日期大小
DateTime.Compare(t1,t2)比較两个日期大小,排前面的小,排在后面的大,比方:2011-2-1就小于2012-3-2返回值小于零: t1 小于 t2. 返回值等于零 : t1 等于 ...
- DOMContentLoaded和window.onload
相信写js的.都知道window.onload吧,可是并非每一个人都知道DOMContentLoaded,事实上即使你不知道.非常有可能你也常常使用了这个东西. 普通情况下,DOMContentLoa ...
- OpenCV原则解读HAAR+Adaboost
因为人脸检测项目.用途OpenCV在旧分类中的训练效果.因此该检测方法中所使用的分类归纳.加上自己的一些理解.重印一些好文章记录. 文章http://www.61ic.com/Article/DaVi ...
- 【转】QT样式表 (QStyleSheet)
作者:刘旭晖 Raymond 转载请注明出处Email:colorant@163.comBLOG:http://blog.csdn.net/colorant/ 除了子类化Style类,使用QT样式表( ...
- cocos2dx 3.2 定义自己使用rapidjson阅读json数据
一.说明 我在这里得到的只是一个简单的定义string和Int种类,其他数据类型可以被替换向上. 两.头文件 class JsonReadUtils { public: static JsonRead ...
- 2048 Puzzle游戏攻略
2048 Puzzle这是目前手机游戏的很火. 在地铁上经常看到的人玩这个游戏. 首先,简介2048 Puzzle游戏. 游戏界面是4X4广场格,每一方格可以放置在数字. 有四种移动数字的方法,向左. ...
- 将DataTable 数据插入 SQL SERVER 数据库
原文:将DataTable 数据插入 SQL SERVER 数据库 以下提供3中方式将DataTable中的数据插入到SQL SERVER 数据库: 一:使用sqlcommand.executenon ...
- 升级iOS8系统后,保险箱Pro、私人保险箱、私密相冊打开就闪退的官方解决方式
升级iOS8系统后,保险箱Pro.私人保险箱.私密相冊打开就闪退的官方解决方式 写在前面的话: 1. 本文适用条件 适用于:您的保险箱Pro.私人保险箱.私密相冊在iPhone或iPad ...