17.Java位运算

17.Java位运算
转载请保留原文链接: http://dashidan.com/article/java/basic/17.html

位运算是通过二进制计算的方式来改变数据.位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算.位运算符可以分为逻辑运算符(包括~,&,|和^)及移位运算符(包括>>,

① Java进位方式

在Java语言中, 二进制数使用补码表示, 最高位为符号位, 正数的符号位为0, 负数为1.

补码的表示规则:

  • 正数的最高位为0,其余各位代表数值本身(二进制数).
  • 对于负数,通过对该数绝对值的补码按位取反,再对整个数加1.

2进制

2进制即为满2进1. 第n位表示2^(n-1)(2的n-1次幂). 数据在计算机内存中以二进制的形式存储.以int类型举例, 占4个字节共32位(1个字节占8位). 数字100, int类型的二进制数:

    0000 0000 0000 0000 0110 0100

数字太长, 不便于理解.因此C,C++以及java中都没有提供在代码直接写二进制数的方法.

8进制

8进制即为满8进1. 第n位表示8^(n-1)(8的n-1次幂). 一个数如果采用八进制, 必须在它前面加上一个数字0.

例:

package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 */
public class Demo1 {
    public static void main(String[] args) {
        /** 10进制*/
        int a = 100;
        /** 8进制*/
        int b = 0100;
        System.out.println("a: " + a + " b: " + b);
    }
}

输出:

a: 100 b: 64

用8进制表达时,不能少了最前边的数字`0`.否则计算机会当成10进制处理.但用转义字符表达时,不能加0.

16进制

16进制即为满16进1. 第n位表示16^(n-1)(16的n-1次幂). 10-15的数字分别以字母a到f表示, 不区分大小小. 16进制数必须以0x开头.x不区分大小写.

package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 */
public class Demo1 {
    public static void main(String[] args) {
        /** 10进制*/
        int a = 100;
        /** 8进制*/
        int b = 0100;
        /** 16进制*/
        int c = 0x100;
        System.out.println("a: " + a + " b: " + b + " c: " + c);
    }
}

输出:

a: 100 b: 64 c: 256

0x中的0是数字0,而不是字母O

真相只有一个

8进制和16进制只能用来表达无符号的正整数?

网上有资料这样说, 但这个是错误的. 8进制和16进制同样可以表示负数.

附带真相的代码:

package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 */
public class Demo1 {
    public static void main(String[] args) {
        int d = -0100;
        int e = -0x100;
        System.out.println("d: " + d + " e: " + e);
    }
}
输出: d: -64 e: -256

② 位运算逻辑运算符

位运算逻辑运算符包括: 与(&),非(~),或(|),异或(^).

  • &: 与. 当两边操作数的位同时为1时, 结果为1, 否则为0.

例:

1100&1010=1000 

位运算判断奇偶, 偶数的最低位是0,奇数的最低位是1.通过这个原理, 我们可以根据整数二进制最后一位与1比较, 判断奇偶.

package com.dashidan.lesson16;

import java.util.Random;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 * 位运算判断奇偶
 */
public class Demo2 {
    public static void main(String[] args) {
        /** 随机一个整数*/
        int a = new Random().nextInt();
        /** 判断奇偶性*/
        String numStr = ((a & 1) == 1) ? "奇数" : "偶数";
        System.out.println("随机数为: " + a + " 是: " + numStr);
    }
}

输出:

随机数为: 476218275 是: 奇数
  • |: 或. 当两边操作数的位有一边为1时,结果为1,否则为0.

例:

1100|1010=1110
  • ~: 按位取反. 0变1,1变0.

负数在内存中的表现是, 按位取反再加1.

  • ^: 按位异或. 参与运算的两个值,如果两个相应位相同,则结果为0,否则为1.

0异或任何数等于任何数, 1异或任何数等于任何数取反, 任何数异或自己等于把自己置0

即:

0^0=0
1^0=1 
0^1=1 
1^1=0

不用临时变量交换两个数

通过按位异或运算,可以实现两个值的交换,而不必使用临时变量. 这个很酷.

例:

交换两个整数a,b的值,可通过下列语句实现:

package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 * 不用临时变量交换两个数
 */
public class Demo3 {
    public static void main(String[] args) {
        /** 数a两次异或同一个数b(a=a^b^b)仍然为原值.*/
        int a = 100;
        int b = 666;

        a = a ^ b;
        b = b ^ a;
        a = a ^ b;

        System.out.println("a: " + a + " b " + b);
    }
}

输出:

a: 666 b 100

数a两次异或同一个数b(a=a^b^b)仍然为原值.

③ 移位运算符

java移位运算符包括:

  • <<:左移位
  • >>:带符号右移
  • >>>:无符号右移

1.左移位运算符(<<)

使指定值的所有位都向左移规定的次数, 丢弃最高位, 在低位补0. 在数字没有溢出的前提下,对于正数和负数, 左移一位都相当于乘以2的1次方, 左移n位就相当于乘以2的n次方.

如果位数超过了该类型的最大位数, 该值将变为负值.

格式:

value << num 

num 指定要移位值value 移动的位数.

如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模.

如对int型移动33位,实际上只移动了33%32=1位.

计算过程:
4<<2为例

    1.把3转换为二进制数字0000 0000 0000 0000 0000 0000 0000 0100, 
    2.把该数字高位(左侧)的两个零移出,其他的数字都朝左平移2位, 
    3.在低位(右侧)的两个空位补零.得到的最终结果是0000 0000 0000 0000 0000 0000 0001 0000, 
    转换为十进制是12. 
package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 * 移位运算符
 */
public class Demo4 {
    public static void main(String[] args) {
        int a = 4;
        int b = a << 2;
        System.out.println("a: " + a + " b: " + b);
    }
}

输出:

a: 4 b: 16

2.有符号右移位运算符>>

使指定值的所有位都向右移规定的次数.正数在高位插入0,负数则在高位插入1. 右移一位相当于除2, 右移n位相当于除以2的n次方.

格式如下:

value >> num 

num 指定要移位值value 移动的位数.

package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 * 移位运算符
 */
public class Demo4 {
    public static void main(String[] args) {
        int a = 4;
        int b = a << 2;
        System.out.println("a: " + a + " b: " + b);

        int c = 1000;
        int d = c >> 2;
        System.out.println("c: " + a + " d: " + d);
    }
}

输出:

c: 1000 d: 250

3.”无符号”右移位运算符(>>>).

忽略了符号位扩展,无论正负,都在高位插入0.

格式如下:

value >>> num 

num指定要移位值value移动的位数.

package com.dashidan.lesson16;

/**
 * 大屎蛋教程网-dashidan.com
 * <p>
 * Java教程基础篇: 16. Java位运算
 * 移位运算符
 */
public class Demo4 {
    public static void main(String[] args) {
        int e = -1;
        int f = e >>> 2;
        System.out.println("e: " + e + " f: " + f);
    }
}

输出:

e: -1 f: 1073741823

只是对32位和64位的值有意义.这一运算符是C或C++没有的.

char,byte或者short移位

在移位前,它们会自动转换成一个int. 移位操作符右端的那个数(转化成二进制)的5个低位才会用到, 即x

④ 位运算符的优先级

~的优先级最高,其次是<<,>>和>>>,再次是&,然后是^,优先级最低的是|.

⑤ 相关文章

Java从入门到精通

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值