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.20
0.2*2=0.40
0.4*2=0.80
0.8*2=1.61
0.6*2=1.21
0.2*2=0.40 // 开始循环

因此我们可以看出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编程的逻辑》第一部分第二章

posted @   顾的江小鱼  阅读(114)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示