2.Java-数据背后的二进制
1.负数用二进制如何表示
首先整数类型有 byte、short、int、long,分别占1、2、4、8个字节,表示范围如下
(1) 什么是补码表示法
我们10用二进制的表示是1010,那么-10如何表示,我们来看代码输出的结果
System.out.println(Integer.toBinaryString(10)); //1010
System.out.println(Integer.toBinaryString(-10)); // 11111111111111111111111111110110
我们知道,int在计算机中占4字节,32位,其中最高位是符号位,为1表示负数,为0表示正数,那么10在计算机中实际原码是 00000000000000000000000000001010,打印时前面的0省略了。
在十进制中,负数是直接在正数前面加一个负号表示。在二进制中,根据上述输出结果可以看到,不是直接把10的原码前面0换成1来表示-10的,否则-10的原码应该是10000000000000000000000000001010,而不是11111111111111111111111111110110。负数的表示方法,叫补码表示法,就是在原码表示的基础上取反然后加1。取反就是将0变为1,1变为0。
(2) 为什么用补码表示法
我们知道 10+-10=0,只有用补码表示,才能够在二进制中,使得10和-10相加为0
1 -> 00000001
-1 -> 11111111
+ ------------------
0 -> 00000000
(3) 正数相加的结果为负数
byte a = 127;
byte b = 1;
System.out.print((byte)(a + b)); // 结果是-128。前面必须通过byte强转,因为print入参是int类型
byte在计算机中是1个字节,8位,表示数值范围是-128 ~ 127(10000000 ~ 01111111),所以当127再加1时二进制则是10000000,超出byte正数能表示范围。
2.小数的二进制
(1) 小数相乘结果出错?
float f = -0.1f * 0.1f;
System.out.println(f); // -0.010000001,和预期0.01不符
我们将0.1转换为2进制,乘2取整
0.1*2=0.2 取 0
0.2*2=0.4 取 0
0.4*2=0.8 取 0
0.8*2=1.6 取 1
0.6*2=1.2 取 1
0.2*2=0.4 取 0 // 开始循环
因此我们可以看出0.1用二进制无法精确表示,实际二进制是0.0001100110011...(0011无限循环),二进制只能表示那些可以表述为2的多少次方和的数:
(2) 小数二进制如何表示
计算机中小数称为浮点数,表示小数点的点浮动不固定,科学计数法为m× (2^e),m称为尾数,e称为指数。小数的两种格式 float、double分别是32位(1位表示符号,23位表示尾数,8位表示指数)和64位(1位表示符号,52位表示尾数,11位表示指数)。查看二进制表示
System.out.println(Integer.toBinaryString(Float.floatToIntBits(0.1f)));
System.out.println(Long.toBinaryString(Double.doubleToLongBits(0.1d)));
书籍:18年出版/机械工业出版社/马俊昌/《Java编程的逻辑》第一部分第二章
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下