热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java位运算—基础与常见问题总结

写在前:从现代计算机中所有的数据二进制的形式存储在设备中。即0、1两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运

写在前:从现代计算机中所有的数据二进制的形式存储在设备中。即0、1两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算。

我们每一种语言最终都会通过编译器转换成机器语言来执行,所以直接使用底层的语言就不需要便编译器的转换工作从而得到更高的执行效率,当然可读性可能会降低,这也是为什么汇编在大部分情况下有更快的速度。

位运算基础

在Java中,位运算符有很多,主要有与(&)、非(~)、或(|)、异或(^)移位(>与>>>),详细说明如下表所示。

Java位运算 --- 基础与常见问题总结
image.png

注意以下几点:

  • 在这6种操作符,只有 ~ 是单目操作符,其它5种都是双目操作符。

  • 位操作只能用于整型数据,对 floatdouble 类型进行位操作会被编译器报错。

  • 位操作符的运算优先级比较低(低于算数运算符),所以尽量使用括号来确保运算顺序,否则容易计算出错。比如要得到像 1,3,5,9 这些 2^i+1 的数字。写成 int a = 1 是不对的,程序会先执行 i + 1,再执行左移操作。应该写成 int a = (1 。

  • 另外位操作还有一些复合操作符,如 &=、|=、 ^=、>=

  • 运算符的优先级:~ 的优先级最高,其次是 > 和 >>>,再次是&,然后是 ^,优先级最低的是 |。

常用技巧

1.判断奇偶

使用&1运算判断奇偶,主要依据一个最未位是 0 还是 1 来决定,为 0 就是偶数,为 1 就是奇数。如1,为… 0001,2为… 0010。

if (a == 5)
a & 1 == 1 替换 a % 2 == 1  //奇数
if (a == 2)
a & 1 == 0 替换 a % 2 == 0  //偶数

2.不使用交换两个数

private void swap1(int[] arr, int i, int j) {
    if (i == j) return;
    arr[i] ^= arr[j];
    arr[j] ^= arr[j];
    arr[i] ^= arr[j];
}

public void swap2(int[] arr,  int i,  int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

注意:当下标i == j 时,异或运算结果都为0,会出现错误。解决方案:(1)加判断,如上swap1();(2)使用tmp变量,如swap2()所示。

异或原地交换值涉及规则:

  • 异或运算满足交换律
  • 相同的数异或结果为0
  • 任何数与0异或都不变

3.位掩码

在Web开发中,为了实现一个良好的访问控制系统,权限和角色管理是个很重要的部分,而如何保存、修改某个角色的权限,是个很值得思考的问题(当然,这个在任何涉及权限控制的系统中都适用)。而在某些情况下,某个组件可能具有多个可叠加的属性状态,这个也可以使用位掩码。

在这种情况下,使用位掩码的话,可以提供很大的灵活性,并且可以相对地减少存储空间(相对于你使用权限的集合或者多个布尔值来表示)。

位掩码的思想是,每个位表示一种权限或者属性,1表示具有,0表示不具有。这样,仅仅使用n个位,就可以表示2^n个权限状态。

举个栗子,数据库的基本操作:增(INSERT)、删(DELETE)、改(UPDATE)、查(SELECT)。我们需要四个位来表示这些权限:

int INSERT=1

如果我们以变量permission存储权限的话,以INSERT为例,可以有下面这些操作:

permission |= INSERT;//添加权限
permission &= ~INSERT;//删除权限
bool allowed = (permission & INSERT) == INSERT;//是否具有权限

4.子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

来源:力扣(LeetCode 78)链接:https://leetcode-cn.com/problems/subsets

示例:输入: nums = [1,2,3]

输出:

[
 [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

分析:事实上n个元素的集合的子集共有2^n个(包含空集),集合的每个元素,都有可以选或不选,如下图所示{A, B, C}的子集分析:

Java位运算 --- 基础与常见问题总结

A 元素为 100 = 4; B元素为010 = 2; C元素为001 = 1
若要构造某个集合,即使用A,B,C对应的三个整数依次与该集合对应的整数做&运算,当为真(为1)时,将该元素push进集合。

代码实现:

public List> subsets(int[] nums) {
    List> ans = new ArrayList();
    int n = nums.length, count = 1  sub = new ArrayList();
        for (int j = 0; j > j) & 1) == 1) {    // 第j位存在,加入子集中
                sub.add(nums[j]);
            }
        }
        ans.add(sub);
    }
    return ans;
}

PS:

  • count = 1
  • i >> j :就是 i 化为二进制的存储,整体右移 j 位

5.待补充…

参考链接:
https://www.cnblogs.com/ktyanny/archive/2009/12/25/1632297.html
https://blog.csdn.net/zmazon/article/details/8262185


推荐阅读
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了一道网络流题目hdu4888 Redraw Beautiful Drawings的解题思路。题目要求以行和列作为结点建图,并通过最大流算法判断是否有解以及是否唯一。文章详细介绍了建图和算法的过程,并强调在dfs过程中要进行回溯。 ... [详细]
  • 本文主要复习了数据库的一些知识点,包括环境变量设置、表之间的引用关系等。同时介绍了一些常用的数据库命令及其使用方法,如创建数据库、查看已存在的数据库、切换数据库、创建表等操作。通过本文的学习,可以加深对数据库的理解和应用能力。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • steps/train_mono.sh
    定义拓扑结构、参数初始化$gmm-init-mono--shared-phones$langphonessets.int--train-feats$featssubset-fe ... [详细]
author-avatar
paalanjorrisch_270
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有