数据结构算法【1】位运算

本文深入解析Java中的位运算,包括int和Long类型的二进制表示,重点讲解左移运算符(<<)、按位与(&)以及取反(~)操作。通过实例演示如何提取二进制位,以及如何进行负数的位运算。同时,探讨了带符号和不带符号的右移(>> 和 >>>)的区别,并展示了其在负数上的应用。
摘要由CSDN通过智能技术生成

位运算

在Java代码中一个数看起来是十进制,其实底层都是 二进制的数 。

int 整形是 32位的 二进制数。 Long 类型是64位的。

打印一个 int 整形数字, 32位的二进制数如下 :

  public static void main(String[] args) {

        int a = 3;
        print(a);

    }

    public static void print(int num ){
        for(int i =31 ; i >= 0 ; i--){
                // 1 左移 i 位
            System.out.print((num & (1 << i )) == 0 ? "0" : "1");
        }
        System.out.println();
    }


结果:
00000000000000000000000000000011   

1:00000000000000000000000000000001
2:00000000000000000000000000000010
3: 00000000000000000000000000000011
4: 00000000000000000000000000000100


这就是一个32位的二进制数,
从 0 ~ 31 位。从右侧开始是0,到最左侧是第31位。分别对应 2⁰ ~ 2³¹ 。
如果该位置位1,则计算;为0,则不计算

   

首先解释下代码含义 

&两个位都为1时,结果才为1 
<<左移各二进位全部左移若干位,高位丢弃,低位补0

  

for(int i =31 ; i >= 0 ; i--){
                // 1 左移 i 位
    System.out.print((num & (1 << i )) == 0 ? "0" : "1");
}

& 与 :

int 整形变量 num 是32位,循环32次和1的左移操作做【与】操作,1每次左移【i】位,如果两个位置都是1,那么就打印1,否则打印0 。

比如 要提取 num 2进制数的第6位,那就让 1 左移 6 位(1 << 6),与其做 与 , 如果是1 ,那就打印出1 .

左移:

各二进位全部左移若干位,高位丢弃,低位补0

比如 【 13 】这个数字, 二进制是 

// 数字 13 的二进制
00000000000000000000000000001101
// 13 <<3     左移 3 位,右侧补0      右侧补了3个0
00000000000000000000000001101000

如果数字太大,左移溢出了呢,那就丢弃

int c = 1322222222;
        print(c);
        print(c << 3);
打印结果: 左移3位, 高位丢弃
01001110110011111000001010001110
01110110011111000001010001110000

负数:

32位的二进制数字,最高位31位【0】代表是正数;【1】代表是负数。所以最大数就是 0 ~ 2 ³¹ -1  。

 整形最大数字: 

int max = Integer.MAX_VALUE;
System.out.println(max);
print(max);
打印结果:
2147483647
01111111111111111111111111111111

如何计算负数: 

负数计算就是 正数取反加1

 int j = 9;
 int j1 = -j;
 int j2 = ~j + 1;

j1 和 j2 是一样的结果;值都是 -9 
j2 就是 取反加1

负数: 符号(第31)位是 1, 后面的值取反(正的是0,那就取1;正的是1,那就取0),再加个1 。

  • 举例如下: 数字【1】
// 1 的正数
00000000000000000000000000000001
// 1 的负数
11111111111111111111111111111111

首先最高位是符号位,1代表是负数,然后不管符号位了,剩下的正1的值取反,(正的是0,那就取1;正的是1,那就取0),
那这样结果就是 11111111111111111111111111111110 , 
最后再加个1 就是: 
11111111111111111111111111111111 。  
  • 举例数字【13】
//13
00000000000000000000000000001101
//-13
11111111111111111111111111110011   
<1>首先正13取反结果:  
11111111111111111111111111110010 , 
<2>然后再加个1 ,结果:
11111111111111111111111111110011

取反 : ~   

一个数字 N,相反数怎们求  ?  直接负号和 N取反加1是相同的结果,就是表示它的相反数

取一个数的相反数,为何要 取反加1,就是可以在做运算的时候,底层走一套逻辑。不需要区分这个数是正数还是负数。

       2
一个数,相反数怎们求  ?
 int k = 9;
 // 第一种方法:直接 ”-“ 负号
 int p = -k;
 // 第一种方法:取反加1; [~]符号就是取反的意思
 p = ~k + 1;
 System.out.println(p);
 print(k);
 print(p);

Console:
-9
00000000000000000000000000001001
11111111111111111111111111110111


 十进制的 加减乘除,其实都是将十进制数翻译成二进制数,做 

|  有一个是1 ,就可以是1

&  两个都是1,才是1

^  相同为0,不同为1

~   取反 

这些位运算的。


右移 : 

右移就是往右边移动 N 位,右移之后,左侧用谁来补?0,还是 1 ?,所以右移有两种方式分别是:

 >> (带符号右移)    :右移后,左侧空位用符号位来补;如果原来的数符号位是0,那就用0来补;如果原来的数是个负数,符号位是1,那就用1来补空位

>>>(不带符号右移):右移后,左侧空位不用符号位来补,直接用0来补

int j = 9;
print(j);
print(j >> 1);

结果如下:
00000000000000000000000000001001
00000000000000000000000000000100

使用负数右移举例: 

  int j = -965454646;
  print(j);
  print(j >> 1);  //这是带符号右移

Console:
11000110011101000101010011001010
11100011001110100010101001100101

-- 可以看到,右移之后,用原来的符号1 ,来填补左边的空位


====================================================================
【不带符号右移】
 j = -965454646;
 print(j);
 print(j >>> 1);  // 不带符号右移

Console:
11000110011101000101010011001010
01100011001110100010101001100101

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值