深入FLOAT,DOUBLE类型内存存储设计

背景:浮点存储方式

这里以6.1为例。
例如:

小数输出对应二进制字符串代码(前面的0不输出)二进制输出(符号位+指数位+尾数位)
6.1(float)Integer.toBinaryString(Float.floatToIntBits(6.1f))0 10000001 10000110011001100110011
6.1(double)Long.toBinaryString(Double.doubleToLongBits(6.1))0 10000000001 1000011001100110011001100110011001100110011001100110

接下来,恭喜 ----- 全是提问~~ 别急着走,先往下看~

浮点指数位范围疑问

浮点中指数位以阶码形式存储,float 指数范围是 -128 ~ 127;

规定:-128的补码是1000 0000。
原码 +0 与 -0 转换为 阶码 是 0111 1111,
因 -128的补码为1000 0000,则转换为 阶码 也是 0111 1111?
这样明显不对,-128的阶码应该有别的数。。

从下表可以发现:
阶码为 1111 1111的值被闲置了(-128 ~ 127都没有值与其对应),
阶码为 1111 1111 的数难道就是 -128? 这是规定吗?如果是规定,如果是,则 -128的补码按规则转换成阶码方式是错误的?

十进制二进制原码二进制阶码
-1280111 1111?
-1271111 1111 (补码1000 0001)0000 0000
-11000 0001(补码1111 1111)0111 1110
-01000 00000111 1111
+00000 00000111 1111
10000 00011000 0000
20000 00101000 0001
1270111 11111111 1110

浮点输出疑问

疑问一:
*6.1f 存储的是 0 10000001 10000110011001100110011,转换成十进制只能是6.099999904632568,下面的代码为何却能正常打印成 6.1;
两个float类型相加也没有丢失精度,why?

这里有需要借助汇编来理解的必要吗?


		float shoultScore = 6.1f;
		System.out.println(shoultScore);// 输出 6.1
		//两个6.1f相加得到的二进制应该是 1100.001100110011001100110应该是输出12.199999809265137
        System.out.println(6.1f+6.1f);  // 输出 12.2 
        System.out.println(6.1f*2);  // 输出 12.2


        //下面这个打印正常,float6.1和double6.1存储后的二进制相加即可得到该值
        System.out.println(6.1f+6.1);   // 输出 12.199999904632568 
        //以下这样输出float6.1 能得到预期的值
		BigDecimal bd = new BigDecimal(shoultScore);
        System.out.println("BigDecimal : " + bd);

疑问二:

如下输出,为何float与double相乘就丢失进度了,,同类型相乘能正常显示。。。是因为同类型二进制计算后的结果换算成十进制恰巧就是 305吗反之就得到304.9999952316284?

        System.out.println("6.1f * 0.5f * 100 = " + 6.1f*0.5f*100); //6.1f * 0.5f * 100 = 305.0
        System.out.println("6.1f * 0.5 * 100 = " + 6.1f*0.5f*100);  //6.1f * 0.5 * 100 = 304.9999952316284
        System.out.println("6.1 * 0.5 * 100  = " + 6.1*0.5*100);    //6.1 * 0.5 * 100  = 305.0

浮点反编译疑问

通过反编译工具 jad 编译 double i = 6.1;得到的结果是

double i = 6.0999999999999996D; 

而 javap中是 6.1D。 float类型就不存在这个问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值