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

关于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的补码按规则转换成阶码方式是错误的?

十进制 二进制原码 二进制阶码
-128 0111 1111?
-127 1111 1111 (补码1000 0001) 0000 0000
-1 1000 0001(补码1111 1111) 0111 1110
-0 1000 0000 0111 1111
+0 0000 0000 0111 1111
1 0000 0001 1000 0000
2 0000 0010 1000 0001
127 0111 1111 1111 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类型就不存在这个问题

你可能感兴趣的:(JAVA基础)