原创文章,转载请标注出处:《Java基础系列-二进制操作》

概述

Java源码中涉及到大量的二进制操作,非常的复杂,但非常的快速。

Java二进制表示法

首先了解下二进制,二进制是相对十进制而言的,当然还有八进制,十六进制等等,我们常用的都是十进制,计算机用的都是二进制,而符号表示常用十六进制。

二进制就是只有0、1两个值表示的数,规则是逢二进一。

整数表示法

Java中使用补码来表示负数,具体就是除符号位之外,剩余位取反加1,符号位不变还是1(符号位0-正数,1-负数)

Java中二进制符号位也不是固定的,在Byte类型的数值中,由于其为一个字节即八位取值范围为-128到127,其符号位就是第8位二进制位。

如下所示:

Byte型数据
1 -> 0000 0001
-1 -> 1111 1111(计算:1为00000001,-1为10000001,取反为11111110,加1为11111111)
127 -> 0111 1111
-127 -> 1000 0001(计算:127为01111111,-127为11111111,取反为10000000,加1为10000001)
-128 -> 1000 0000(计算:128为100000000,取8位为00000000,-128为10000000,取反为11111111,加1为10000000)

Short型数为两个字节16位数值,其符号位为第16位:

Short型数据
1 -> 0000 0000 0000 0001
-1 -> 1111 1111 1111 1111(计算:1为0000000000000001,-1为1000000000000001,取反为1111111111111110,加1为1111111111111111)
32767 -> 0111 1111 1111 1111
-32767 -> 1000 0000 0000 0001(计算:32767为0111111111111111,-32767为1111111111111111,取反为1000000000000000,加1为1000000000000001)
-32768 -> 1000 0000 0000 0000(计算:32768为10000000000000000,取16位为0000000000000000,-32768为1000000000000000,取反为1111111111111111,加1为1000000000000000)

Integer为32位,Long为64位,表示方式如上,Integer第32位为符号位,Long型第64位为符号位。

浮点数表示法

Java中的浮点数大多数都无法精确表示,为什么呢?因为使用二进制来表示小数一样存在和十进制表示小数一样的问题,存在无限循环的小数和无限不循环的小数,比如十进制的1/3,十进制为0.333...无限个3,二进制表示同样会有这个问题,二进制表示0.1、0.2、0.3、0.4等都不能精确表示,0.5可以表示为2^(-1),可以精确表示,可见只有可以精确的使用科学计数法表示的二进制小数才能精确表示,其他的一律无法精确表示。

Java中使用32位的float和64位的double表示浮点小数。

Float型浮点数
格式:1位符号位,8位指数,23位尾数(S1_E8_M23)
符号位:0-正数,1-负数
指数位:采用移位存储,即用真实数值+127的二进制值来表示,比如,1要表示成128(即:10000000),128表示为255(即11111111)
尾数位:将十进制数转化为二进制之后,转化为科学计数法形式,取小数位作为尾数位,不足23位结尾补0
0.5 -> 0011 1111 0000 0000 0000 0000 0000 0000
(计算:0.5 = 1/2,即2^(-1),指数位为-1+127=126,即01111110,尾数为0,因为是正数,符号位为0)
10.5 -> 0100 0001 0010 1000 0000 0000 0000 0000
(计算:10的二进制为1010,0.5的二进制为0.1,所以10.5的二进制Wie1010.1,科学计数法表示为1.0101E11,如此一来,指数位为3+127=130,即10000010,符号位为0,尾数为0101,后面补0,够23位)
35.3 -> 0100 0010 0000 1101 0011 0011 0011 0011
(计算:35的二进制为100011,0.3的为二进制为0.01001100110011001100110011001100110011...,合起来就是100011.0100110011001100110011...,科学计数法为1.00011010011001100110011...E101,如此一来,符号位为0,指数位为5+127=132,即10000100,尾数为00011010011001100110011)
Double型浮点数
格式:1位符号位,11位指数,52位尾数
符号位:0-正数,1-负数
指数位:采用移位存储,用真是数值+1023的二进制值来表示,比如1要表示成1024(即:10000000000)
尾数位:将十进制转化为二进制,再转为科学计数法,取小数位作为尾数,不足52位结尾补0
35.3 -> 0100 0000 0100 0001 1010 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110
(计算:35的二进制为100011,0.3的为二进制为0.01001100110011001100110011001100110011...,合起来就是100011.0100110011001100110011...,科学计数法为1.00011010011001100110011...E101,如此一来,符号位为0,指数位为5+1023=1028,即10000000100,尾数为0001101001100110011001100110011001100110011001100110)

进制转化:

十进制转二进制,整数部分除以2,整除为0,否则为1,直到结果为1,然后从后窜到前的结果就是其二进制值

比如:10
10/2 = 5 整除 0
5/2 = 2 未整除 1
2/2 = 1 整除 0
1 结果为1,结束 1
最后10的二进制值为:1010
再比如77
77/2=38 未整除 1
38/2=19 整除 0
19/2=9 未整除 1
9/2=4 未整除 1
4/2=2 整除 0
2/2=1 整除 0
1 结果为1,结束 1
最后77的二进制为1001101

小数部分的二进制化,取小数部分乘以2,结果大于等于1,取1,否则取0,再取小数部分乘以2,取值,直到结果为0或者循环

比如:10.22
先进行整数部分二进制,结果为1010
再进行小数部分二进制:
0.22 * 2 = 0.44 0
0.44 * 2 = 0.88 0
0.88 * 2 = 1.76 1
0.76 * 2 = 1.52 1
0.52 * 2 = 1.04 1
0.04 * 2 = 0.08 0
0.08 * 2 = 0.16 0
0.16 * 2 = 0.32 0
0.32 * 2 = 0.64 0
0.64 * 2 = 1.28 1
0.28 * 2 = 0.56 0
0.56 * 2 = 1.12 1
0.12 * 2 = 0.24 0
0.24 * 2 = 0.48 0
0.48 * 2 = 0.96 0
0.96 * 2 = 1.92 1
0.92 * 2 = 1.84 1
0.84 * 2 = 1.68 1
0.68 * 2 = 1.36 1
0.36 * 2 = 0.72 0
0.72 * 2 = 1.44 1
...
结果就是1010.00111000010100011110...
若是以科学计数法表示那就是1.01000111000010100011110...E11
若是表示成float的二进制形式那就是:0100 0001 0010 0011 1000 0101 0001 1110

Java二进制运算符

与:&

与操作规则:全1为1,否则为0
例如:
1010 & 0101 = 0000
1111 & 0000 = 0000
1010 & 1111 = 1010
0101 & 0000 = 0000

扩展:二进制中的1的与操作具有保留原值的效果,任何值(0,1)和1进行与操作结果都不会变。这一点在HashMap中得以使用。

或:|

或操作规则:有1为1,全0为0
例如:
1010 | 0101 = 1111
1111 | 0000 = 1111
1010 | 1111 = 1111
0101 | 0000 = 0101

扩展:二进制中的0的或操作也具有保留原值的效果,任何值(0,1)和0进行或操作结果都不会变。

非:~

非操作规则:0为1,1为0
例如:
~1111 = 0000

异或:^

异或操作规则:相同为0,不同为1
例如:
1010 ^ 0101 = 1111
1111 ^ 0000 = 1111
1010 ^ 1111 = 0101
0101 ^ 0000 = 0101

扩展:二进制中的0的异或操作具有保留原值的效果,1的异或操作具有取反的效果。

左移:<<

左移规则:符号位保持不变的情况下剩余全部左移一位,低位补0,相当于乘以2的结果
例如:
0011 << 2 = 1100
1000 0000 1000 0001 << 2 = 1000 0010 0000 0100 (首位1为符号位)

右移:>>

右移规则:符号位保持不变的情况下剩余全部右移一位,高位补0,相当于除以2的结果
例如:
0011 >> 2 = 0000
1000 0000 1000 0001 >> 2 = 1000 0000 0010 0000 (首位1为符号位)

无符号右移:>>>

无符号右移规则:全员右移一位,高位补0,相当于除以2的结果
例如:
1000 0000 1000 0001 >> 2 = 0010 0000 0010 0000 (首位1为符号位)

二进制操作

参考例子中的操作:

public class BinaryTest {
public static void main(String[] args){
int a = 100;
String as = Integer.toBinaryString(a);// 整数的二进制表示,可输出二进制字符串
long b = 200;
String bs = Long.toBinaryString(b);// 长整数的二进制表示,可输出二进制字符串
float c = 30.0f;
int ci = Float.floatToIntBits(c);// 将浮点数的二进制布局解析为整型表示
int ci2 = Float.floatToRawIntBits(c);// 将浮点数的二进制布局解析为整型表示
float f2 = Float.intBitsToFloat(a);// 将整型数的布局解析为一个浮点数
double d = 302.22d;
Long dl = Double.doubleToLongBits(d);// 将浮点数的二进制布局解析为长整型表示
Long dl2 = Double.doubleToRawLongBits(d);// 将浮点数的二进制布局解析为长整型表示
double d2 = Double.longBitsToDouble(b);// 将长整型数的布局解析为一个双精度浮点数
}
}

Java基础系列-二进制操作的更多相关文章

  1. Java基础系列--HashMap(JDK1.8)

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10022092.html Java基础系列-HashMap 1.8 概述 HashMap是 ...

  2. 夯实Java基础系列3:一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!

    目录 目录 string基础 Java String 类 创建字符串 StringDemo.java 文件代码: String基本用法 创建String对象的常用方法 String中常用的方法,用法如 ...

  3. 夯实Java基础系列13:深入理解Java中的泛型

    目录 泛型概述 一个栗子 特性 泛型的使用方式 泛型类 泛型接口 泛型通配符 泛型方法 泛型方法的基本用法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型方法总结 泛型上下边界 泛型常见面试 ...

  4. Java基础系列--static关键字

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8477914.html 一.概述 static关键字是Java诸多关键字中较常使用的一个,从 ...

  5. Java基础系列-ArrayList

    原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...

  6. Java基础系列-Collector和Collectors

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...

  7. Java基础系列-Comparable和Comparator

    原创文章,转载请标注出处:<Java基础系列-Comparable和Comparator> 一.概述         Java中的排序是由Comparable和Comparator这两个接 ...

  8. 夯实Java基础系列1:Java面向对象三大特性(基础篇)

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...

  9. 夯实Java基础系列4:一文了解final关键字的特性、使用方法,以及实现原理

    目录 final使用 final变量 final修饰基本数据类型变量和引用 final类 final关键字的知识点 final关键字的最佳实践 final的用法 关于空白final final内存分配 ...

随机推荐

  1. 面试阿里前端P6血和泪换来的收获

      我的一个朋友在前端耕耘一段时间,也在网上进行了高度培训学习,最近一段时间他打算跳槽去阿里面试前端P6开发岗位,结果被痛虐了一回,估计从此以后会给他留下不可磨灭的阴影啊 真是十年生死两茫茫,一鲁代码 ...

  2. linux 文本编辑 软件管理

    gerp 命令 : grep是强大的文本搜索工具,它对文本文件逐行查看,如果找到匹配的模式,就会打印出包含此模式的所有行,并且grep支持正则表达式 1  grep 选项 模式 被查找文件 : gre ...

  3. 解决eclipse svn 转 maven web 项目中遇到找不到maven managed dependencies的问题

    我们在使用eclipse从svn上check项目下来,然后转成maven web 项目的时候,经常会遇到一个问题,就是找不到maven依赖(maven managed dependencies),从而 ...

  4. 聊一聊快速排序(Js)

    快速排序 基本思路 双指针+递归分治(本质是一个创建二叉树搜索树的过程) 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据 ...

  5. PdfReader按页将PDF切割成多个PDF

    private MemoryStream GetNewPdfByPageNum(PdfReader pdfReader, int pageNum) { MemoryStream memoryStrea ...

  6. 《HelloGitHub》第 36 期

    公告 本期内容较多.本期共有 41 个项目:C# 项目(1),C++ 项目(1),CSS 项目(2),Go 项目(5),Java 项目(2),JavaScript 项目(5),Objective-C ...

  7. synchronized关键字简介 多线程中篇(十一)

    前面说过,Java对象都有与之关联的一个内部锁和监视器 内部锁是一种排它锁,能够保障原子性.可见性.有序性 从Java语言层面上说,内部锁使用synchronized关键字实现 synchronize ...

  8. C# ASP.NET MVC:使用Cookie记住账号密码

    MVC记住账号密码 使用cookie操作 前端: <div> 用户名:<input type="text" id="UserName" val ...

  9. 由浅入深讲解责任链模式,理解Tomcat的Filter过滤器

    本文将从简单的场景引入, 逐步优化, 最后给出具体的责任链设计模式实现. 场景引入 首先我们考虑这样一个场景: 论坛上用户要发帖子, 但是用户的想法是丰富多变的, 他们可能正常地发帖, 可能会在网页中 ...

  10. 正确分析结构使用正确的HTML标签。CSS样式写一起。

    在内容中 一行内容包括三张图片,每张图片下面有标题和具体介绍,那么可以使用: 分析和解决如下步骤: 1,一行三块,先向左浮动成为一行float:left. 2,把他们的宽度平分三份,33.3%.三份都 ...