当前位置: 首页 > news >正文

Java 位运算

基本移位

左移没区别;
右移: 有符号补符号位 (>>); 没符号补 0;

  1. << 表示 左移
    不分正负数,低位补 0
  2. >> 表示 右移
    如果该数为正,则高位补 0
    若为负数,则高位补符号位 (i.e. 1)
  3. >>> 表示 无符号右移, 也叫逻辑右移
    如果该数为正,则高位补 0
    而若该数为负数,则右移后高位同样补 0

算术移位 和 逻辑移位

  1. 逻辑移位: 就是 无符号移位, 左移 <<< 和 右移 >>> 都是补零
  2. 算术移位: 算术移位是对 有符号数 进行的, 符号位不变, 对数值位进行移动补 0 (针对原码)
  • 区别:
    • 逻辑右移 最高位不管是什么都用 0 填充 (相当于 无符号数除 2)
    • 算术右移 最高位 (符号位) 不变, 原码剩余部分补 0 (相当于 有符号数除 2); 补码剩余部分补符号位

算术移位中, 实际设计硬件只实现了 补码的算术移位, 所以右移符合上面的基本移位: 加符号位

python 右移

The right shift in python is arithmetical. 只有算术右移

由于 Python 没有无符号数,因此它不包含无符号移位 (没有 >>>)

补码

tldr;
正数的补码是本身;
0 的补码是 0;
负数的补码是: 符号位不变, 数据位取反, 再 +1 (不会溢出, 因为会溢出的最大值是 -0, 反码 11111111)

计算机中的有符号数有三种表示方法,即原码 original code、反码 inverse code 和 补码 complement code

三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”

而数值位,三种表示方法各不相同

在计算机系统中,数值一律用补码来表示和存储 (原因在于,使用补码,可以将符号位和数值域 统一处理;同时,加法和减法也可以统一处理)

介绍

在介绍补码概念之前,先介绍一下“模”的概念:“模”是指一个计量系统的计数范围,如过去计量粮食用的斗、时钟等。计算机也可以看成一个计量机器,因为计算机的字长是定长的,即存储和处理的位数是有限的,因此它也有一个计量范围,即都存在一个“模”。

如:时钟的计量范围是 0~11,模 = 12。表示 n 位的计算机计量范围是 0 ~ 2n - 1,模 = 2n.“模” 实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。也就是取反后加 1。

假设当前时针指向 8 点,而准确时间是 6 点,调整时间可有以下两种拨法:

  1. 一种是倒拨 2 小时,即8-2=6;
  2. 另一种是顺拨 10 小时,8+10=12+6=6,即8-2=8+10=8+12-2(mod 12).

在 12 为模的系统里,加 10 和减 2 效果是一样的,因此凡是减 2 运算,都可以用加 10 来代替。若用一般公式可表示为:

a-b=a-b+mod=a+mod-b

对“模”而言,2 和 10 互为补数。实际上,以 12 为模的系统中,11 和 1,8 和 4,9 和 3,7 和 5,6 和 6 都有这个特性,共同的特点是两者相加等于模。对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是 11111111,若再加 1 成 100000000 (9位),但因只有 8 位,最高位 1 自然丢失(相当于丢失一个模)。又回到了 00000000,所以 8 位二进制系统的模为。在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。

把补数用到计算机对数的处理上,就是补码。

原码求补码

  1. 求给定数值的补码分以下两种情况:
    1. 正数: 正整数的补码是其二进制表示,与原码相同
      例:+9 的补码是 00001001。(备注:这个+9的补码是用8位2进制来表示的,补码表示方式很多,还有 16 位二进制补码表示形式,以及 32 位二进制补码表示形式,64 位进制补码表示形式等。每一种补码表示形式都只能表示有限的数字)
    2. 负数: 求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加 1
  2. 0 的补码: 数 0 的补码表示是唯一的
    [+0]补 = [+0]反 = [+0]原 = 00000000
    [-0]补 = 11111111 + 1 = 00000000

补码求原码

已知一个数的补码,求原码的操作其实就是对该补码再求补码:

  1. 如果补码的符号位为 “0”,表示是一个正数,其原码就是补码
  2. 如果补码的符号位为 “1”,表示是一个负数,那么求给定的这个补码的补码 (再求补码) 就是要求的原码
    例:已知一个补码为 11111001,则原码是 10000111(-7)。
    解:因为符号位为 “1”,表示是一个负数。
    所以符号位不变,仍为“1”。其余七位 1111001 取反后为 0000110;再加 1,所以是 10000111。

意义

补码“模”概念的引入、负数补码的实质、以及补码和真值之间的关系, 所揭示的补码符号位所具有的数学特征,无不体现了补码在计算机中表示数值型数据的优势,和原码、反码等相比可表现在如下方面:

  1. 解决了符号的表示的问题
  2. 可以将减法运算转化为补码的加法运算来实现,克服了原码加减法运算繁杂的弊端,可有效简化运算器的设计
  3. 在计算机中,利用电子器件的特点实现补码和真值、原码之间的相互转换,非常容易
  4. 补码表示统一了符号位和数值位,使得符号位可以和数值位一起直接参与运算,这也为后面设计乘法器除法器等运算器件提供了极大的方便

总之,补码概念的引入和当时运算器设计的背景不无关系,从设计者角度,既要考虑表示的数的类型(小数、整数、实数和复数)、数值范围精确度,又要考虑数据存储和处理所需要的硬件代价。因此,使用补码来表示机器数并得到广泛的应用也就不难理解了

相关文章:

  • 非公用网络在工业互联网中的部署方案探讨
  • 小红书怎么高效找达人?方法不对导致耗时又不适合
  • java: 无效的目标发行版: 17 新建springBoot项目
  • Polygon zkEVM发布公开测试网2.0
  • 如何在 JavaScript 中格式化日期?
  • 安全网络身份认证系统的设计与实现
  • SOLIDWORKS Electrical 2023新功能揭秘!提高电气工程师设计效率 与机械工程师协同设计
  • 【Java入门基础第10天】Java常用的转义字符
  • URLLC典型应用建模与评估
  • Java反射和new效率差距有多大?
  • 用 Python 制作各种用途的二维码
  • Java项目:springboot电影推荐网站
  • 人脸检测和对齐算法MTCNN
  • 【学习笔记】前端HTML+CSS部分必懂基础内容(面试考察重点)
  • 【架构师(第五十二篇)】 几个前端工具的基本使用
  • 关于为什么要做量化白皮书这件事
  • 韩顺平java-枚举和注解异常包装类
  • Web3中文|可判115年监禁的FTX创始人SBF即将被引渡到美国
  • 【蓝桥杯】第10届Scratch国赛第6题程序1 -- 捉迷藏
  • 【语义感知:IVIF:实时:高级视觉任务循环】