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

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

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


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


位运算基础



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

image.png

image.png


注意以下几点:


  • 在这6种操作符,只有 ~ 是单目操作符,其它5种都是双目操作符。
  • 位操作只能用于整型数据,对 floatdouble 类型进行位操作会被编译器报错。
  • 位操作符的运算优先级比较低(低于算数运算符),所以尽量使用括号来确保运算顺序,否则容易计算出错。比如要得到像 1,3,5,9 这些 2^i+1 的数字。写成 int a = 1 << i + 1; 是不对的,程序会先执行 i + 1,再执行左移操作。应该写成 int a = (1 << i) + 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<<0;//0001
int DELETE=1<<1;//0010
int UPDATE=1<<2;//0100
int SELECT=1<<3;//1000


如果我们以变量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}的子集分析:


image.png

A 元素为 100 = 4; B元素为010 = 2; C元素为001 = 1


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


代码实现:

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> ans = new ArrayList<>();
    int n = nums.length, count = 1 << nums.length;
    for (int i = 0; i < count; i++) {      // 这里对所有子集进行编码0,1...7
        List<Integer> sub = new ArrayList<>();
        for (int j = 0; j < n; j++) {
            if (((i >> j) & 1) == 1) {    // 第j位存在,加入子集中
                sub.add(nums[j]);
            }
        }
        ans.add(sub);
    }
    return ans;
}


PS:


  • count = 1 << nums.length :2 的nums.length 次方,记录子集的数量
  • i >> j :就是 i 化为二进制的存储,整体右移 j 位


5.待补充...



参考链接:

https://www.cnblogs.com/ktyanny/archive/2009/12/25/1632297.html

https://blog.csdn.net/zmazon/article/details/8262185

相关文章
|
6月前
|
编解码 算法 Java
Java中的位运算详解
Java中的位运算详解
|
6天前
|
存储 Java
Java中的位运算
本文介绍了位运算符的基础知识,包括原码、反码、补码的概念,以及常见的位运算符(如移位运算符 `&lt;&lt;`、`&gt;&gt;`、`&gt;&gt;&gt;` 和逻辑运算符 `&`、`|`、`^`、`~`)的使用方法和规则。通过具体的二进制示例,详细解释了这些运算符的工作原理,帮助读者更好地理解位运算在计算机中的应用。
Java中的位运算
|
2月前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
3月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
95 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
7月前
|
Java
【Java基础】输入输出流(IO流)
Java基础、输入输出流、IO流、流的概念、输入输出流的类层次结构图、使用 InputStream 和 OutputStream流类、使用 Reader 和 Writer 流类
227 2
|
3月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
98 2
|
4月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
|
7月前
|
安全 Java
Java多线程编程实践中的常见问题与解决方案
Java多线程编程实践中的常见问题与解决方案
|
6月前
|
编解码 算法 Java
WXM
|
6月前
|
前端开发 JavaScript 小程序
Java人事面常见问题及方法论
Java人事面常见问题及方法论
WXM
61 0