二进制基础:补码,左移,右移

2023-05-16

binary

      • 引入
      • 为什么要有补码
      • 特殊的值
      • 溢出
      • 数学移位
      • 逻辑位移
      • 逻辑右移的应用

引入

二进制是计算机的基础,追根溯源还是因为Si的半导体性。

除了二进制,还有十六进制,它是简化二进制的表示。

做个测试:

  @Test
    public void testHex() {
        int n = 0x77d45d25;
        System.out.println(
                Integer.toBinaryString(n));
    }

0x表示这是一个十六进制数。

结果:

1110111110101000101110100100101

我们自己转换一下:

在这里插入图片描述

控制台输出的结果它把最高位的0给舍掉了,但这个不影响。

为什么要有补码

先看0000到1111的二进制数:

十进制代表的就是0到15

那这里为什么要画成一个圈呢?因为有溢出的概念。

我们等下会测试。

现在的问题是:怎么才能有负数?

解决的办法就是,把0到15这16个数分一半给负数:

这样就ok了。我们终于有负数了。

这么一划分出现了一个神奇的事情:

这个圈圈上的任意一个数,它的二进制取反之后,再加一(顺时针移动一次),会变成原数的相反数!

比如2,它的二进制是0010

取反:1101

加一:1110

在图上看看,1110不就是-2吗?


拿代码测一下:

 @Test
    public void testInverse(){
        System.out.println(~100+1);
    }

结果:

-100

特殊的值

我认为的补码就是因为负数而产生的。

我们观察上面的图,注意几个特别的数:

在四位的情况下:

0—>0000
-1—>1111
最小值 —> 1000
最大值 —> 0111

你需要记住的是,任何位数,-1永远都是一群1。


    @Test
    public void testMore() {
        int n = -9;
        System.out.println("-9的二进制:" + Integer.toBinaryString(n));
        n = -1;
        System.out.println("-1的二进制:" + Integer.toBinaryString(n));


        int max = Integer.MAX_VALUE;
        int min = Integer.MIN_VALUE;
        System.out.println("最大的整数: " + max);
        System.out.println("最小的整数:" + min);

        System.out.println("最大整数的二进制: " +
                Integer.toBinaryString(max));
        System.out.println("最小整数的二进制: " +
                Integer.toBinaryString(min));

   
    }

结果:

-9的二进制:11111111111111111111111111110111
-1的二进制:11111111111111111111111111111111
最大的整数: 2147483647
最小的整数:-2147483648
最大整数的二进制: 1111111111111111111111111111111
最小整数的二进制: 10000000000000000000000000000000

这里是32位,和我们探究的4位理论上是一样的。

那么,如何才能快速知道-9的二进制表示呢?

首先,你知道-1是32个1(11111111111111111111111111111111)

然后,因为-9是-1减掉8,所以你用32个1去减8(1000)

另外一个有趣的地方就是:

最大值加一变成最小值。

这个是正常现象,不能叫做溢出。

我们拿8位的byte做个例子:

    @Test
    public void testbyte() {
        byte b = 127;
        byte ans = (byte) (b + 1);
        System.out.println(ans);
    }

结果:

-128

溢出

还是看4位的情况。

1111如果还要加1,就会溢出。

溢出自动舍去高位:

于是结果就是0000

溢出保证我们的整个逻辑还是正确的。

数学移位

什么是数学移位?

就是>>以及<<

它是二进制数的移动,所以计算起来非常之快。

当然,你完全可以将其理解为乘2和除2。

>>是右移,右移它的数量级就会降低,移一次就会有除以2的效果。

相反,<<是左移,左移一次就会有乘以2的效果。

看个测试:

  @Test
    public void testMoveBit(){
        System.out.println(50>>1);
        System.out.println(50<<1);
        System.out.println(50>>2);
        System.out.println(50<<2);
        System.out.println("------------------------");
        System.out.println(-50>>1);
        System.out.println(-50<<1);
        System.out.println(-50>>2);
        System.out.println(-50<<2);
    }

结果:

25
100
12
200
------------------------
-25
-100
-13
-200

唯一要注意的就是除不尽的时候要取整。

还有一个很经典的问题,就是右移的时候,高位到底是补0还是补1。

用代码看一下就知道了:

  @Test
    public void testMoveBitPositiveAndNegative(){
        System.out.println("positive--------------------");
        System.out.println(Integer.toBinaryString(50));
        System.out.println(Integer.toBinaryString((50>>2)));
        System.out.println("negative--------------------");
        System.out.println(Integer.toBinaryString((-50)));
        System.out.println(Integer.toBinaryString((-50>>2)));
    }

结果:

positive--------------------
110010
1100
negative--------------------
11111111111111111111111111001110
11111111111111111111111111110011

正50它把前面的0全部给省略了,我们自己补上:

正数数学右移的时候,就是高位补0,低位溢出。

负数数学右移的时候,从控制台的结果可以看到,是高位补1,低位溢出。

逻辑位移

逻辑位移只有右移,没有左移,右移的符号是>>>

它的作用很大,源码中经常出现逻辑右移,主要作用就是用来将数字拆分成一个一个字节的。

    @Test
    public void testMoveBitLogic(){
        System.out.println(50>>>1);
        System.out.println(50>>>2);
        System.out.println("------------------------");
        System.out.println(-50>>>1);
        System.out.println(-50>>>2);
    }

结果:


25
12
------------------------
2147483623
1073741811

正数的行为和数学右移很像。但是,它不是用来做数学计算的。所以如果你想要快速地完成除以2的工作,请用>>

负数的右移很奇怪,那就是高位补0还是补1的问题了。

测试:

    @Test
    public void testMoveBitLogicBinary(){
        System.out.println("positive--------------------");
        System.out.println(Integer.toBinaryString(50));
        System.out.println(Integer.toBinaryString((50>>>2)));
        System.out.println("negative--------------------");
        System.out.println(Integer.toBinaryString((-50)));
        System.out.println(Integer.toBinaryString((-50>>>2)));
    }

结果:

positive--------------------
110010
1100
negative--------------------
11111111111111111111111111001110
111111111111111111111111110011

正数的时候和数学右移一样,都是高位补0。

负数的时候,我们睁大眼睛看看:


负数逻辑右移,是高位补0,低位溢出。

逻辑右移的应用

看一下RandomAccessFilewriteInt方法:

 public final void writeInt(int v) throws IOException {
        write((v >>> 24) & 0xFF);
        write((v >>> 16) & 0xFF);
        write((v >>>  8) & 0xFF);
        write((v >>>  0) & 0xFF);
        //written += 4;
    }

可以看出来,它是一个一个字节写出去的,从高八位开始。

其实在网络传输中,传输的都是字节,所以也会用到逻辑右移。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二进制基础:补码,左移,右移 的相关文章

随机推荐

  • 入门DP | 2:租用游艇问题

    租用游艇问题 成绩10开启时间2020年03月24日 星期二 23 15折扣0 8折扣时间2020年04月21日 星期二 23 55允许迟交否关闭时间2020年04月21日 星期二 23 55 问题描述 长江游艇俱乐部在长江上设置了n个游艇
  • 本人亲测解决ipython及jupyter不能使用tensorflow的问题

    1 在ipython下无法使用的解决方案 尝试在Anaconda lib site packages中新建path pth文件 xff0c 里面内容为指定的虚拟环境名下的lib site packages位置 例如 xff1a D Prog
  • 树莓派连接“手机热点“或“WiFi“ 后无法上网,以及连接“手机热点“或“WiFi“时VNC连接失败问题

    问题描述 之前一直在开热点 xff0c 通过电脑端VNC控制树莓派拍摄照片 xff0c 今天突然发现树莓派上不去网 xff0c 所以就试着尝试解决了一下 xff0c 心路历程如下 xff1a 要么就是树莓派连不上网 xff0c 要么就是连上
  • 基于python批量调整图像大小

    前言 在写论文的时候常常因为截图的尺寸大小不一样 xff0c 导致图片排版很难受 xff0c 在word中又不会批量修改 xff0c 用下面的代码可以批量处理修改成一样的尺寸哦 xff01 代码如下 xff1a 在本文中 xff0c 我将向
  • Nginx 命令

    nginx 启动Nginx nginx s reopen 重启Nginx nginx s reload 重新加载Nginx配置文件 xff0c 然后以优雅的方式重启Nginx nginx s stop 强制停止Nginx服务 nginx s
  • jieba,为中文分词而生的Python库

    jieba xff0c 为中文分词而生的Python库 中文分词 xff0c 通俗来说 xff0c 就是将一句 段 话按一定的规则 算法 拆分成词语 成语 单个文字 中文分词是很多应用技术的前置技术 xff0c 如搜索引擎 机器翻译 词性标
  • MDK的内嵌汇编与内联汇编

    内联汇编 asm 34 指令 34 这是内联汇编 而MDK下 xff0c 内联汇编仅支持ARM汇编语言 xff0c 不支持Thumb或者Thumb 2汇编语言 xff0c 但内嵌汇编器支持Thumb和Thumb 2 STM32的core c
  • 【李刚-21天通关Python-08】之 字典

    李刚 21天通关Python 08 之 字典 一 字典的概念 1 字典用于保存具有映射关系的数据 xff0c 字典相当于保存了两组数据 xff0c 其中一组数据被称为key xff0c 另一组数据可通过key来访问 xff0c 被称为val
  • 按键精灵 百度文字识别(百度ocr)OCRSpace文字识别

    目录 1 申请百度OCR服务1 1 百度OCR登录1 2 创建新应用1 3 免费领取次数1 3 查看是否创建成功 2 按键精灵运用百度OCR接口2 1 通用文字识别 xff08 高精度版 xff09 文档2 1 1 接口描述2 1 2 请求
  • Ubuntu系统扩大/home分区

    gparted是一款免费 开源的Linux下的具有图形用户界面的分区软件 在Ubuntu中 xff0c 可以使用如下命令安装 xff1a sudo apt get install gparted 之后就可以使用如下命令启动gparted s
  • sqlsever导入sql文件

    sqlsever导入sql文件 新建一个数据库 xff0c 数据库名与到导入的文件的数据库名一致 把文件拖入当前窗口 xff0c 把创建表的语句删除 xff0c creat table到go语句之前 xff08 因为创建表的路径不一样 xf
  • Python接口自动化——自动化测试分层(1)

    从本期开始 xff0c 我们会围绕 Python接口自动化 做专题连载 xff0c 今天开始做第一讲 自动化测试分层 目录 xff1a 1 1 1 1 单元自动化测试 2 1 1 2 接口自动化测试 3 1 1 3 UI自动化测试 现在流行
  • C++快读模板(读入整型数据)

    先上代码 span class token macro property span class token directive keyword include span span class token string lt iostream
  • Linux安装jenkins2.3详解

    Linux安装jenkins2 3详解 下载 官网下载jenkins xff0c 我们选择rpm包进行安装 xff1a 地址 xff1a https mirrors jenkins ci org redhat https get jenki
  • 程序设计思维 week4 作业C-TT 的神秘礼物

    题目 TT 是一位重度爱猫人士 xff0c 每日沉溺于 B 站上的猫咪频道 有一天 xff0c TT 的好友 ZJM 决定交给 TT 一个难题 xff0c 如果 TT 能够解决这个难题 xff0c ZJM 就会买一只可爱猫咪送给 TT 任务
  • 程序设计思维 week11 作业E-东东与ATM

    题目 一家银行计划安装一台用于提取现金的机器 机器能够按要求的现金量发送适当的账单 机器使用正好N种不同的面额钞票 xff0c 例如D k xff0c k 61 1 2 N xff0c 并且对于每种面额D k xff0c 机器都有n k张钞
  • 程序设计思维 CSP-M3

    T1 瑞神的数列 题目 Sample Input 12 2 3 3 6 6 6 1 1 4 5 1 4 Sample Output 8 思路 利用vector xff0c 使用vector lt int gt v储存数字 若v为空 xff0
  • ubuntu一段时间后突然无法上网

    在VMware中安装Ubuntu虚拟机 xff0c 总会发生无法上网的情况 xff0c 主要情况有以下几点 xff1a 宿主机可以上网 xff1b 虚拟机却无法访问网页虚拟机ping不通任何网站 xff0c 用浏览器显示error 一般情况
  • STM32 - 使用 HAL 库实现软件模拟 I2C

    不要让自己太懒的个人空间 I2C 的两个引脚 xff08 SCL 引脚和 SDA 引脚 xff09 需要既能输出又能输入 xff0c 为了避免复杂的配置操作需要把该引脚配置为开漏输出模式 xff0c 该模式的说明如下图所示 xff1a 当单
  • 二进制基础:补码,左移,右移

    binary 引入为什么要有补码特殊的值溢出数学移位逻辑位移逻辑右移的应用 引入 二进制是计算机的基础 xff0c 追根溯源还是因为Si的半导体性 除了二进制 xff0c 还有十六进制 xff0c 它是简化二进制的表示 做个测试 xff1a