前言

讲二进制的东西,必须要说明是多少位机器,八位机上的 1000 1000 和 十六位机上的 1000 1000 ,那能是一回事嘛,差远了。

我用 java 中的规范来讲这个知识,一来我是写 java 的,二来忘记了大一那时候学C的情况,也不想考察CC艹int,这些数据类型跟机器位数的关系。


机器数

可以理解为给我们人看的二进制,注意计算机中保存数据用的二进制,根本不是这个机器数,而是后面说的 补码

比如,数字 3 ,在 java 中整数,默认是 int 类型,占用4个字节,所以,它的机器数是 0000 0000,0000 0000,0000 0000,0000 0011

数字 -3 的机器数: 1000 0000,0000 0000,0000 0000,0000 0011

在二进制中,最高位是符号位,0 代表正数,1 代表负数,其中符号位是不参与进位的 ;


真值

就是除去符号位,剩下的位的二进制转成十进制,再配上正负号的值。我们要看一串 0101001010,是看它真值的,而不是看他二进制直接转成十进制是多少。

比如, 1000 0000,0000 0000,0000 0000,0000 0011 的真值是 -3 ,二进制直接转成十进制却是 2147483651


原码

原码跟机器数是一样的。

还是数字 3

原码是 0000 0000,0000 0000,0000 0000,0000 0011

数字 -3

原码是 1000 0000,0000 0000,0000 0000,0000 0011

正数、负数的原码都是机器数。


反码

还是数字 3

原码是 0000 0000,0000 0000,0000 0000,0000 0011

反码是 0000 0000,0000 0000,0000 0000,0000 0011

数字 -3

原码是 1000 0000,0000 0000,0000 0000,0000 0011

反码是 1111 1111,1111 1111,1111 1111,1111 1100

正数的原码和反码是一样的。负数的反码是由原码保存符号位不变,其他位取反得到的。


补码

还是数字 3

原码是 0000 0000,0000 0000,0000 0000,0000 0011

反码是 0000 0000,0000 0000,0000 0000,0000 0011

补码是 0000 0000,0000 0000,0000 0000,0000 0011

数字 -3

原码是 1000 0000,0000 0000,0000 0000,0000 0011

反码是 1111 1111,1111 1111,1111 1111,1111 1100

补码是 1111 1111,1111 1111,1111 1111,1111 1101

正数的原码和反码是一样的。负数的补码是由反码 +1,得到的,并且这个加法操作产生的进位,不能进位到符号位。


计算机中保存的都是补码

比如 -3,看下它对应的二进制数据。

因此,看到一个二进制数,想要知道它表示的数值是多少,其实就是求其真值的过程。

但是有特殊的存在,比如补码是 1000 0000,0000 0000,0000 0000,0000 0000这种符号位为 1,其他位全是 0 的存在,是没有反码、原码的。它们表示的值,是除符号位为 0,其他位为 10111 1111,1111 1111,1111 1111,1111 1111 的真值 +1 的相反数 。

给你一个二进制,要看看它是什么,才能准确的说出什么。


位操作

前面讲那么多,引入正题,java 中的位操作。

便于理解,我们这里说的一个十进制数的二进制形式都是 补码,不是原码,不是我们常规看到的二进制直接转十进制!毕竟,计算机位运算的时候,也是直接补码来的

  1. >> 无符号右移

    规则:

    • 符号位不变
    • 高位补符号位的数值,即符号位是 1 ,就补充 1,反之亦然 。
    • 数值上的变化是,模运算 ,移动几位,就模 2 的几次方(在没有溢出的情况下) ;
    • 如果移动的位数,超过了数据本身的位数,则实际移动的位数是当前位数的取模

    byte 类型的 -128 ,右移动 2 位:

    1000 0000 >> 2 = 1110 0000 = -32

  2. << 有符号右移动

    规则:

    • 符号位跟随移动
    • 低位补 0
    • 数值上的变化是,乘法,移动几位,就乘以 2 的几次方 ;
    • 重要的一个规则,如果数据类型是 byte、short 会被自动的提升到 int 类型。
    • 提升后的数据类型,多出来的高位,全部用符号位填充。
    • 如果移动的位数,超过了数据本身的位数,则实际移动的位数是当前位数的取模

    byte 类型的 -128 ,左移动 2 位:

    1000 0000 << 2 = 1111 1111,1111 1111,1111 1111,1000 0000 << 2 = 1111 1110 0000 0000 = -512 ;

    byte 类型的 -128 ,左移动 62 位,其实是左移动 62 % 32 = 30 位:

    1000 0000 << 62 = 1111 1111,1111 1111,1111 1111,1000 0000 << 30 = 0000 0000,0000 0000,0000 0000,0000 0000 = 0 ;

  3. >>> 无符号右移动

    规则:

    • 符号位跟随移动
    • 高位补 0

    byte 类型的 -128 ,无符号右移 2 位:

    1000 0000 >>> 2 = 0010 0000 = 32 ;

主要记住一个对右操作数取模运算。


强制转换,精度丢失

类似于xx=这样的操作符号,比如 >>=、<<=、+=,-=,底层是有个强制转换的;

最简单的:

	byte a = 127 ;
byte b = a + 10 ; // error 数据类型溢出
a += 10 ; // ok ,底层被类型强制转换了

移位也是一样的:

	byte b = -64;
System.out.println(b<<3); // 值是 -512
System.out.println(b<<=3); // 被强制转换以后,只取低8位,值是 0

二进制知识(java中的位操作)的更多相关文章

  1. 深入Java中的位操作

    「WTF系列」深入Java中的位操作 关于WTF系列 引 学完本章节你将学会位的基础概念与语法,并且还会一些骚操作!! 与.或.非.位移 原码.反码.补码 字节.位.超区间...... 开始本章节之前 ...

  2. java中的位操作

    之前做项目的时候使用位操作不是很多,今天在刷leetcode上题目的时候用到了位操作,是leetcode中的第29题Divide Two Integers. 一.java的位操作: 位运算表达式由操作 ...

  3. 二进制之Java中的进制(二)

    1. jdk中的进制转换 十进制转十六进制 Integer.toHexString(int i); 十进制转八进制 Integer.toOctalString(int i); 十进制转二进制 Inte ...

  4. java中无符号类型的处理

    在Java中,不存在Unsigned无符号数据类型,但可以轻而易举的完成Unsigned转换. 方案一:如果在Java中进行流(Stream)数据处理,可以用DataInputStream类对Stre ...

  5. (转)java 中unsigned类型的转换

    转自:http://blog.sina.com.cn/s/blog_77bf45a90101dld9.html 在Java中,不存在Unsigned无符号数据类型,但可以轻而易举的完成Unsigned ...

  6. JAVA中常用的二进制位操作

    一,计算某个正数的二进制表示法中 1 的个数 //求解正数的二进制表示法中的 1 的位数 private static int countBit(int num){ int count = 0; fo ...

  7. Java中的二进制及基本的位运算

    Java中的二进制及基本的位运算 二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二 ...

  8. java中关于IO流的知识总结(重点介绍文件流的使用)

    今天做软件构造实验一的时候,用到了java文件流的使用,因为之前学的不是很踏实,于是决定今天好好总结一下, 也方便以后的回顾. 首先,要分清IO流中的一些基础划分: 按照数据流的方向不同可以分为:输入 ...

  9. 二进制原码、反码、补码以及Java中的<< 和 >> 和 >>> 详细分析

    1.计算机二进制系统中最小单位bit 在计算机二进制系统中: bit (位) :数据存储的最小单元. 简记为b,也称为比特(bit),每个二进制数字0或1就是一个位(bit),其中,每 8bit = ...

随机推荐

  1. 急急急,tp5的验证码不显示

    本地环境phpstudy,使用composer安装tp5,按照看云<ThinkPHP5.0完全开发手册>验证码配置,就是不显示验证码. 使用:<div>{:captcha_im ...

  2. STP生成树算法

    生成树算法第一:决定谁是“根网桥”对比各个网桥ID,先对比ID中的优先级,优先级相同的时候对比网桥MAC地址,对比依据是谁的值最小,谁是“根网桥” 第二:决定哪些是“根端口”窍门——每个非根网桥上都有 ...

  3. 深度学习面试题09:一维卷积(Full卷积、Same卷积、Valid卷积、带深度的一维卷积)

    目录 一维Full卷积 一维Same卷积 一维Valid卷积 三种卷积类型的关系 具备深度的一维卷积 具备深度的张量与多个卷积核的卷积 参考资料 一维卷积通常有三种类型:full卷积.same卷积和v ...

  4. android strings: %s、%1$s、%d、%1$d占位符

    实际开发的过程中我们有时候会遇到,一个TextView里面会遇到会有一个一大串固定的文字,而里面的数字或者个别字需要根据后台的接口而展示的.这个时候我们最简单的方法就是在string.xml文件里 使 ...

  5. 蓝牙BLE: 蓝牙4.0 BLE广播数据解析(转)

    BLE 设备工作的第一步就是向外广播数据.广播数据中带有设备相关的信息.本文主要说一下 BLE 的广播中的数据的规范以及广播包的解析. 1. 广播模式 BLE 中有两种角色 Central 和 Per ...

  6. Leetcode: 24 Game

    You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated ...

  7. flutter 权限申请

    添加依赖 permission_handler: ^3.2.2 androidmanifest.xml添加对应的用户权限 在flutter 中app入口申请权限: import 'package:fl ...

  8. flutter 页面布局 Paddiing Row Column Expanded 组件

    Flutter Paddiing 组件 在 html 中常见的布局标签都有 padding 属性,但是 Flutter 中很多 Widget 是没有 padding 属 性.这个时候我们可以用 Pad ...

  9. axios请求数据完整

    <template> <!-- 所有的内容要被根节点包含起来 --> <div id="home"> 首页组件 <button @clic ...

  10. 使用localStorage写一个简单的备忘录

    使用html+js实现一个简单的备忘录,主要体会一下localStorage的用法. 先看看效果图: 在输入框中输入文字,点击保存按钮,文本内容会在下放展示出来, 然后刷新下浏览器,会发现文本内容不会 ...