位运算总结&拾遗
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#位运算来处理. 第 ...
随机推荐
- CodeForces 52C Circular RMQ(间隔周期段树,间隔更新,间隔总和)
转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://codeforces.com/problemset/problem/52/C You are g ...
- ArrayList实现借壳
随着Collections工具: import java.util.ArrayList; import java.util.Collections; public class TTEST { publ ...
- paip.android环境搭建与开发事例
paip.android环境搭建与开发事例 好长时间没有玩AndROID了..以前常常做ANDROID的,今天决定在下载一个要做个时间设置器 作者Attilax , EMAIL:1466519819 ...
- 点击 下载 pdf
<iframe id="fileDownFrame" src="" style="display:none; visibility:hidde ...
- ubuntu下安装wine
直接在终端里面输入“sudo apt-get install wine”不要引号,即可安装wine.至于使用它,终端命令就是“wine ....”举个例子,你现在要运行魔兽, 然后你的魔兽的文件夹的位 ...
- 重新想象 Windows 8 Store Apps (26) - 选取器: 自定义文件选取窗口, 自定义文件保存窗口
原文:重新想象 Windows 8 Store Apps (26) - 选取器: 自定义文件选取窗口, 自定义文件保存窗口 [源码下载] 重新想象 Windows 8 Store Apps (26) ...
- hdu 5092 Seam Carving
这道题 我没看出来 他只可以往下走,我看到的 8-connected :所以今天写一下如果是 8-connected 怎么解: 其实说白了这个就是从上到下走一条线到达最后一行的距离最小: 从Map[a ...
- Android Java汉字转拼音总结
转载请表明出处:http://blog.csdn.net/lmj623565791/article/details/23187701 开发过程中有时候会遇到使用拼音模糊搜索等功能(典型的就是Andro ...
- jQuery照片伸缩效应,这不是一个简单的图像缩放,它不影响其它元素的布局
之前在网上看到这样的效果,但我没有收藏夹网址,后来被我不知道如何来实现这种效果. 如今,互联网已收集有关专门.真是功夫不负有心人,被我发现. 我也努力过自己尝试着写: 但仅仅是单纯的图片放大.并且还影 ...
- JSON.stringify 语法解释
行为:此函数的作用主要是串行化对象. 或许有些人是过敏的字系列.我非常理解easy.是对象的类型转换成字符串类型(或者更确切的说是json类型的).就这么简单.打个例如说,你有一个类,那么你能够通过这 ...