JAVA浮点数二进制详解

日期:2014-09-01 21:05:46

留言:6

分类:学习记录

标签: Java

十进制科学记数法

98765 = 9.8765 * 104
              尾数        基数指数

二进制科学记数法

1)1010 1011 = 1010 1011. * 20

2)1010 1011 = 1010 101.1 * 21

3)1010 1011 = 1010 10.11 * 210

4)1010 1011 = 1010 1.011 * 211

4)……

5)1010 1011 = 1.010 1011 * 2111

                           尾数              基数指数

小数点二进制科学记数法

101.0 1011(2) = 1.010 1011 * 210(2) = 5.34375(10)

二进制小数转十进制方法:

22 + 20 + 2-2 + 2-4 + 2-5 = 5.34375

指数2,0,-2,-4,-5分别代表二进制数中第2,0,-2,-4,-5位是1,0忽略,完整的写法是:

22 + 01 + 20 + 0-1 + 2-2 + 0-3 + 2-4 + 2-5 = 5.34375

十进制小数转二进制方法:

1)5.34375整数位为5,转二进制为101;

2)小数位0.34375 * 2 = 0.6875,整数位为0,结果101.0;

3)继续0.6875 * 2 = 1.375,整数位为1,结果101.01;

4)去掉整数继续乘2,0.375 * 2 = 0.75,结果101.010;

5)循环到没有小数为止……;

6)最终结果:101.01011。

float(32bit)二进制存储结构

01000 00010101 0110 0000 0000 0000 000
符号位指数(8bit)尾数(23bit)

原理说明:

1)第1位为符号位,0为正数,1为负数;

2)第2-9位为指数位,共8位,不足8位前面补0,由于指数没有符号位,不能表示负数,只能通过将结果减127来得到负数,所以指数位存储的结果是原指数加127,即指数2存储后指数为 2+127 = 129(10) = 1000 0001(2);

3)第10-32位为尾数位,共23位,不足23位后面补0,尾数位包含隐藏的1.X,即1.010 1011只存储0101 011,然后后面补0,最终结果为0101 0110 0000 0000 0000 000。

float转十进制方法:

1)符号位0为正数;

2)指数转十进制,1000 0001为129,需要减127,所以指数为129-127=2;

3)尾数去掉后面的0,结果为0101 011;

4)尾数前面加1. 即:1.010 1011;

5)指数为2,小数点往后移2位,即:101.0 1011;

6)转十进制22 + 20 + 2-2 + 2-4 + 2-5 = 5.34375。

代码验证:

  float f = 5.34375f;
  System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));

采用double(64bit)二进制表示方式

00010 0000
001
0101 0110 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000
0000
符号位指数(11bit)尾数(52bit)

原理说明:

1)第1位为符号位,0为正数,1为负数;

2)第2-12位为指数位,共11位,不足11位前面补0,由于指数没有符号位,不能表示负数,只能通过将结果减1023来得到负数,所以指数位存储的结果是原指数加1023,即指数2存储后指数为 2+1023 = 1025(10) = 10000000 1(2);

3)第13-64位为尾数位,共52位,不足23位后面补0,尾数位包含隐藏的1.X,即1.0101011只存储0101011,然后后面补0,最终结果为0101 0110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000。

double转十进制方法:

1)符号位0为正数;

2)指数转十进制,1000 0000 001为1025,需要减1023,所以指数为1025-1023=2;

3)尾数去掉后面的0,结果为0101 011;

4)尾数前面加1. 即:1.010 1011;

5)指数为2,小数点往后移2位,即:101.0 1011;

6)转十进制22 + 20 + 2-2 + 2-4 + 2-5 = 5.34375。

代码验证:

  double d = 5.34375;
  System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));

PS:double转换方法与float一致,区别在指数位算法有所差异,且尾数大小远远超过了float,因此精度也大大提高,正常情况下浮点数均采用double。

给我留言
留言表
ALAN :
点赞 2020-03-09 20:27:06
ZengDongwu 回复 土样 :
或者你可以同过int的数据来验证一下,int是32bit的,控制台输出
System.out.println(Integer.toBinaryString(1));
和输出
System.out.println(Integer.toBinaryString(-1));
对比一下,当然int二进制是补码存储的喔,所以负数就不是仅仅首位区分,希望能帮到你。 2018-03-26 13:57:06
ZengDongwu 回复 土样 :
你好,float二进制是32bit存储的,控制台上输出的字符串前面是0的都默认没有显示出来,所以完整的32位前面还有一个0,你数数你看到的是不是31位 。  :)
另外你可以试试负数 float f = -5.34375f; 的输出看看结果。 2018-03-26 13:54:48
土样 :
float f = 5.34375f;
        System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));

为什么输出来的是 1000000101010110000000000000000
和你的不同 2018-03-23 21:50:59
ZengDongwu 回复 听海的大象 :
是的,很开心能帮助到你:) 2016-09-18 23:36:23
听海的大象 :
你好,你的这个博客是自己做的吗?感觉好厉害、
你的这篇博客解决了我的疑惑,谢谢。 2016-09-17 12:41:44