位运算

作者: hello_mr_future | 来源:发表于2022-09-08 12:38 被阅读0次

    在数学领域123属于整数、实数、正数等等,而在计算机领域123属于十进制数,即以10为基数的n次方的数制,当然面向对象是人类,那么对于计算机底层逻辑来讲,怎么存储123 这个数字呢?我们认知的正数、负数在计算机中是如何进行存储的呢?又是如何进行运算的呢?

    123是如何在计算机中进行存储的

    答:用0,1表示的二进制进行存储的。

    这里默认大家都知道java中的int类型数和long类型数,我们都知道java中的int类型数是32位,long类型是64位,那这32位是什么呢?没错,就是32个0,1组成的数制。
    先给答案,int类型数 123 在计算机中的存储:

    00000000000000000000000001111011
    

    如上就是123在计算机中的存储形式。那么怎么和十进制进行转换的呢?我们都知道二进制就是以2为基数的数制,逢二进一,和十进制进行转换即以2为基n的次方计算求得,其中n表示的就是哪一位上非0,从右向左分别为0,1,2...以此类推。
    那么上面的可以进行计算为:

    2^0 + 2^1 +  2^3 + 2^4 + 2^5 + 2^6 = 123
    

    那么从二进制转换为十进制数如此,十进制转换为二进制即为相反的过程,此处不在赘述。

    正数、负数在计算机中如何存储

    答:最高位0表示正数,1表示负数

    举个例子

    10000000000000000000000001111011 最左边的1表示此数是一个负数
    00000000000000000000000001111011 最左边的0表示此数是一个正数

    在计算机中数字是如何进行计算的

    此处先讲一下简单的加法运算,后续再讲复杂的运算。加法运算和我们在十进制数是一样的,两数相加,“逢二进一”。

    与C语言不同,Java中没有无符号整数

    • 无符号数顾名思义就是没有正负之说,它的范围是0~2^32-1,并且它最高
      位的0或者1没有意义,表示数值。
    • 有符号数是区分正数和负数的,范围是-2^31~ 2^31 -1 ,最高位上的0表示正数,1表示负数

    举个例子

    • 正数的表示和转换为十进制数上述有例子,此处进行展示,不做详细(123)
    00000000000000000000000001111011
    

    计算方式

    2^0 + 2^1 +  2^3 + 2^4 + 2^5 + 2^6 = 123
    
    • 负数的表示和转换为十进制数(-123)
    11111111111111111111111110000101
    

    计算方式

    便于计算机的快速性,也为了解决有无符号的一个通用性,使计算机底层对于任何数都是同一个计算方式,此处对于负数的计算有一个巧思:“取反加一”

    ~+1(取反加一)
    第一步取反:
    1 0000000000000000000000001111010 // 最高位的1不在计算数值中,表示负号(-)
    第二步+1
    1 0000000000000000000000001111011 
    -(2^0 + 2^1 +  2^3 + 2^4 + 2^5 + 2^6) = -123
    

    总结一下:-123在计算机中存储是

    11111111111111111111111110000101
    

    它转换为十进制数时最高位表示负号不计数,后面的31位进行“取反加一”的操作后通过基底转换即可得到十进制数-123。

    数讲完了,那什么是位运算呢?

    位运算是程序设计中对位模式按位或二进制数的一元和二元操作。
    古老的架构中,位运算是略快于加减法运算,比乘除法运算要快很多
    现代的架构中,位元算和加法运算速度是相同的,但仍快于乘除法运算

    位运算符

    ~ 取反
    & 按位与
    | 按位或
    ^ 按位异或
    << 左移
    >> 带符号右移
    >>> 不带符号右移

    取反

    一元运算,具有右结合性
    例:~(1001) 取反后得---> 0110

    按位与

    二元运算,都是1即为1,其余均是0。
    例:1 & 1 = 1,1 & 0 = 0,0 & 1 = 0,0 &0 = 0

    按位或

    二元运算,有1即为1。
    例:1 | 1 = 1,1 | 0 = 1,0 | 1 = 1, 0 | 0 = 0

    按位异或

    二元运算,相同为0,不同为1(相异为1)
    例:1^1 = 0,1^0 = 1,0^1 = 1,0^0 = 0

    左移

    二元运算,左移n位就是乘以2的n次方,高位丢弃,低位补0。
    例:1左移1位,1<<1 = 2; 简单用8位数表示 00000001 << 1 == 00000010
    ⚠️ 当左移的数值超过int类型的边界,会出现溢出的情况

    int num = Integer.MAX_VALUE;
    print(num);
    print(num << 1);
    System.out.println(num<<1);
    
    //输出结果
    01111111111111111111111111111111
    11111111111111111111111111111110
    -2
    
    
    int num = Integer.MIN_VALUE;
    print(num);
    print(num << 1);
    System.out.println(num<<1);
    
    //输出结果
    10000000000000000000000000000000
    00000000000000000000000000000000
    0
    

    带符号右移(有符号数)

    二元运算,右移n位表示除以2的n次方。
    带符号右移的意思是,当最高位是1右移时高位空出位置补1,当最高位是0右移时高位空出位置补0。同理,当右移后的数值大于int类型的边界,则会溢出。

     int numRight = Integer.MIN_VALUE;
     print(numRight);
     print(numRight >> 1); //带符号右移,依然表示负数
     System.out.println(numRight >> 1);
    
    //输出结果
    10000000000000000000000000000000
    11000000000000000000000000000000
    -1073741824
    

    不带符号右移(无符号数)

    二元运算,右移n位表示除以2的n次方,。最高位不管是0还是1,空出的高位均补0。

     int numRight = Integer.MIN_VALUE;
     print(numRight);
     print(numRight >>> 1); //不带符号右移,表示正数
     System.out.println(numRight >>> 1);
    
    //输出结果
    10000000000000000000000000000000
    01000000000000000000000000000000
    1073741824
    

    此处可以看出来,当不带符号右移时,负数会变成正数。

    再补充一下相反数,a的相反数是-a,-a的相反数是a
    它的表述方式:-a 和 ~a + 1(“取反加一” 也表示相反数)a 为任何数
    ⚠️0的相反数是0,可通过“取反加一”观察,-2^31相反数是本身,也可通过“取反加一”计算出来。

     int num = 0;
     int numFan = -num;
     int numFan1 = ~num + 1;
    
     print(num);
     print(numFan);
     print(numFan1);
    
    //输出结果
    00000000000000000000000000000000
    00000000000000000000000000000000
    00000000000000000000000000000000
    
    
    
    
      int num = Integer.MIN_VALUE;
      int numFan = -num;
      int numFan1 = ~num + 1;
    
      print(num);
      print(numFan);
      print(numFan1);
    
    //输出结果
    10000000000000000000000000000000
    10000000000000000000000000000000
    10000000000000000000000000000000
    

    相关文章

      网友评论

          本文标题:位运算

          本文链接:https://www.haomeiwen.com/subject/vemanrtx.html