数字编码:

参考: https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

  • 原码:符号位+真值

反码:正数同原码,负数:符号位不变,真值取反

补码:正数同原码,负数:符号位不变,真值取反+1

  • 目的:简化计算机的基础电路,将符号位也参与运算,这样所以机器可以只有加法而没有减法
  • 补码的补码 = 原码

数学原理: 同余定理

Java位移

参考:

https://blog.csdn.net/qq_41892229/article/details/82874928

byte的取值范围为-128~127,占用1个字节(-2的7次方到2的7次方-1)

short的取值范围为-32768~32767,占用2个字节(-2的15次方到2的15次方-1)

int的取值范围为(-2147483648~2147483647),占用4个字节(-2的31次方到2的31次方-1)

long的取值范围为(-9223372036854774808~9223372036854774807),占用8个字节(-2的63次方到2的63次方-1)

左移 <<

  • 高位移除,在低位补0;
  • 在没有数字溢出的前提下,左移1位相当于乘以2的1次方,左移n位相当于乘以2的n次方。

  • 在左移过程中正数可能移为负数,负数也可能移为正数。

  • 当左移的操作数是int类型时,每移动一位它的第31位就要被移除(位数以第0位开始);
  • 当左移的操作数是long类型时,每移动一位 它的第63位就要被移除;
  • 当左边的操作数为byte、short类型时,它们会被转换为int类型,其结果要是int类型。

-101: 补码 00000000 00000000 00000000 10011011

左移1位:00000000 00000000 00000001 00110110

换算成原码(方便人脑计算数值):00000000 00000000 00000001 11001010 = -202

右移(有符号)>>

  • 若符号为正,则在高位插入0,若符号为负,则在高位插入1(符号位保持不变);
  • 操作数为byte、short类型时,它们会被转换为int类型,其结果要是int类型。
  • 右移一位相当于除以2,右移n位相当于除以2的n次方。

  • 无论正负偶数左移一位直接是整除结果,但对于正值奇数结果是除以2后向下取整后的结果。

​ 对于负值奇数结果是除以2后向上取整结果。

偶数(60) 直接除以2(30) 直接除以2(-30)
奇数(61) 除以2后向下取整(30) 除以2后向上取整(-31)

-101: 补码 00000000 00000000 00000000 10011011

有符号右移2位:00000000 00000000 00000000 11100110

换算成原码(方便人脑计算数值):00000000 00000000 00000000 10011010 = -26

右移(无符号)>>>

  • 无论数值是正数还是负数,都在最高位补0

位移只对32位和64位值有意义

shift_only_int_long

猜测因为位移操作都是在32位寄存器中完成的???


在Thinking in java 中有这么一句话:

只有数值右端的低5位才有用,这样可以防止我们移位超过int型值所具有的位数。(因为2的5次方为32,而int类型只有32位)若对一个long类型的数值进行处理,最后得到的结果也是long类型,此时只会用到数值右端的低6位,以防止移位超过long型数值具有的位数

换言之,如果移动位数超过该类型的最大位数,那么编译器会对移动的位数取模。例如果对int类型移位33位,实际上只移动了33%32=1位。具体细节是(int a<<b)如果移位超过数值类型的最大位数,就将b化为二进制数,取右端的低5位数,再把这5位数化为10进制,此时这个10进制就是要将a移动的位数,long 类型同理。

results matching ""

    No results matching ""