关于位运算:位运算的使用

对于位运算位运算就是二进制运算,咱们晓得计算机cpu运算最底层的物理实现,就是高低电平输出,形象成数学符号就是二进制01输出。因而位运算对cpu来说是最高效的,因为咱们用它的“母语”和它交换。因而,juc库很多中央都有位运算的影子,就是为了提高效率,有的中央用得奇妙真是让人惊叹,让人大呼还能这样,既优雅又简洁,应了中国的那句老话,大道至简! 使用示例给定一个整型容量initialCapacity,计算这个容量最近的2的n的数 initialCapacity = numElements; initialCapacity |= (initialCapacity >>> 1); initialCapacity |= (initialCapacity >>> 2); initialCapacity |= (initialCapacity >>> 4); initialCapacity |= (initialCapacity >>> 8); initialCapacity |= (initialCapacity >>> 16); initialCapacity++;上述代码翻译成人类语言就是,给定一个数,咱们从二进制的角度看这个数;比方8,它的二进制是1000;把它最高位1之后的其余位都变成1,而后加1;即1000 -> 1111,加1后变成10000,对应的十进制是16. 下面这段代码其实是摘自ArrayDeque的 allocateElements,其实它还思考了溢出变成正数状况,就是二进制最高位是1的状况。 相似的还有jdk1.8 hash map的容量初始化修改计算,为啥cap要先减去1,为了使得输出刚好是2的n次方的数的容量不须要再修改,比方8,对应的二进制是1000,减去1后的二进制是0111,对应的十进制是7,用同样的算法,算出后果是8,和输出的8统一。

June 5, 2022 · 1 min · jiezi

关于位运算:lowbit的原理和应用

家喻户晓,lowbit是为了获取一个数的二进制中最低位的1对应的值,比方lowbit(10) = 10,因为10的二进制表白是1010。 lowbit的实现lowbit有两种实现形式: x & (x ^ (x - 1))以二进制数x = 11110000为例,x - 1=11101111,容易发现,其实就是将x的最初一个1变为0,再将前面的0都变成1,这样以来,再与x做异或: 11110000 ^ 11101111后果是00011111。也就是把原数x最初一个1以及前面的 0都变成1,把最初一个1后面的1都变成0。既然后面都是零了,那么只有和原数x做和的操作,即可将异或的后果最初一个1前面的1都变成0,也就是 11110000 & 00011111失去00010000,这样就优雅得失去了最初一个1示意的数,也就是原数x的最大的能够整除的数。这里x的十进制是240,lowbit的后果是16=2^4。x & -x这种算法其实是利用了计算机的补码性质。计算机为了示意正数,将对应的负数二进制全副取反再加一。以x=11010000为例,-x=00101111 + 1 = 00110000,能够看到,取反加一后原数最初一个1前面的所有0还是0(因为加法的进位操作),原数最初一个1前的所有1都变成了0,而所有0都变成了1,其实次要外围就是将最初一个1后面的数都翻转,这样再与原数进行或操作,最初一个1后面都会是0,也就是 11010000 & 00110000后果是00010000。lowbit的利用统计二进制下1的个数先用原数计算出lowbit(x),而后用原数减去这个数,再一直lowbit。int ans = 0;while(x > 0){ x -= x & -x; ans++;}这也是树状数组的实现原理。基于这个操作咱们能够将合成出一个整数能够由哪些的2的幂相加形成。比方11110000也就是240=2^4+2^5+2^6+2^7。 参考: https://www.jianshu.com/p/6c3...https://blog.csdn.net/qq_4172...https://www.cnblogs.com/fusiw...

March 4, 2022 · 1 min · jiezi

关于位运算:剑指-Offer-65-不用加减乘除做加法

class Solution { public int add(int a, int b) { while(b!=0) { int c = (a & b)<<1; int n = a ^ b; a = n; b = c; } return a; }}

January 12, 2021 · 1 min · jiezi

关于位运算:剑指-Offer-56-I-数组中数字出现的次数

异或满足交换律,第一步异或,雷同的数其实都对消了,剩下两个不同的数。这两个数异或后果必定有某一位为1,不然都是0的话就是雷同数。找到这个位,不同的两个数一个在此位为0,另一个为1。按此位将所有数分成两组,离开后各自异或,雷同的两个数异或必定为0(而且离开的时候,两个数必为一组)。剩下的每组里就是我门要找的数 class Solution { public int[] singleNumbers(int[] nums) { //用于将所有的数异或起来 int k = 0; for(int num: nums) { k ^= num; } //取得k中最低位的1 int mask = 1; //mask = k & (-k) 这种办法也能够失去mask,具体起因百度 哈哈哈哈哈 while((k & mask) == 0) { mask <<= 1; } int a = 0; int b = 0; for(int num: nums) { if((num & mask) == 0) { a ^= num; } else { b ^= num; } } return new int[]{a, b}; }}作者:eddieVim链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/solution/jie-di-qi-jiang-jie-fen-zu-wei-yun-suan-by-eddievi/起源:力扣(LeetCode)著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

January 12, 2021 · 1 min · jiezi

关于位运算:前端玩转位运算N皇后Vue3位运算应用

观感度:???????????????????? 口味:西南小炒肉 烹饪工夫:10min 本文已收录在前端食堂同名仓库Github github.com/Geekhyt,欢迎光临食堂,如果感觉酒菜还算可口,赏个 Star 对食堂老板来说是莫大的激励。初识位运算记忆& ,与 两个位都为 1 时,后果才为 1| ,或 两个位都为 0 时,后果才为 0^ ,异或 两个位雷同为 0 ,相异为 1~,按位取反 所有 0 变 1,1 变 0<<,左移 各二进位全副左移若干位,高位抛弃,低位补 0>>,右移 各二进位全副右移若干位,对无符号数,高位补 0 ,有符号数,各编译器解决办法不一样,有的补符号位,有的补 0了解其实很简略,小学数学题难度,花几分钟看完如果看懂了请点个赞呗。 左移二进制左移一位,就是将数字翻倍。 二进制 110101 向左移一位,就是在开端增加一位 0,也就是 1101010。(此处探讨的是数字没有溢出的状况) 二进制 110101 转化成十进制: 1 2^5 + 1 2^4 + 0 2^3 + 1 2^2 + 0 2^1 + 1 2^0 = 32 + 16 + 0 + 4 + 0 + 1 ...

December 10, 2020 · 5 min · jiezi