关于Java中的IEEE765浮点数表示法

理解这篇文章的几个要点:1.了解进制转换原理;2.理解指数偏移量的含义和原理;3.了解数据在内存中的存放方式(顺序)。——博主注

www.360doc.com中转帖【IEEE浮点数表示法】,经过仔细研究,终于有点心得了。

float转十六进制:

16进制浮点数的表示方法,根据IEEE的标准,分为32位和64位两种,参数分别如下:

 

             符号位      指数位      尾数位       指数偏移量
32位   1[31]          8[23-30]     23[0-22]      127 
64位   1[63]          11[52-62]   52[0-51]      1023


float
共计32位,折合4字节
由最高到最低位分别是第31、30、29、……、0位
31位是符号位,1表示该数为负,0反之。
30-23位,一共8位是指数位。
22-0位,一共23位是尾数位。

现在让我们按照IEEE浮点数表示法,一步步的将float型浮点数123456.0f转换为十六进制代码。

在处理这种不带小数的浮点数时,直接将整数部转化为二进制表示:1 11100010 01000000。

也可以这样表示:11110001001000000.0。

然后将小数点向左移,一直移到离最高位只有1位,就是最高位的1:1.11100010010000000。

一共移动了16位,在布耳运算中小数点每向左移一位就等于在以2为底的科学计算法表示中指数+1,所以原数就等于这样:1.11100010010000000 * ( 2 ^ 16 )。

好了,现在我们要的尾数和指数都出来了。显而易见,最高位永远是1,因为你不可能把买了16个鸡蛋说成是买了0016个鸡蛋吧?所以这个1我们还有必要保留他吗?好的,我们删掉他。

这样尾数的二进制就变成了:11100010010000000最后在尾数的后面补0,一直到补够23位:11100010010000000000000。

再回来看指数,一共8位,可以表示范围是0 - 255的无符号整数,也可以表示-128 - 127的有符号整数。

但因为指数是可以为负的,所以为了统一把十进制的整数化为二进制时,都先加上127(说得是什么玩意儿!!表达不清)在这里,我们的16加上127后就变成了143,二进制表示为:10001111。


12345.0f这个数是正的,所以符号位是0,那么我们按照前面讲的格式把它拼起来:
0 10001111 11100010010000000000000
01000111 11110001 00100000 00000000


再转化为16进制为:47 F1 20 00,最后把它翻过来,就成了:00 20 F1 47。——内存的存储方式

==========================================================

按照IEEE浮点数表示法,将float型浮点数123.456f转换为十六进制代码。

整数部直接化二进制:100100011。

小数部的处理比较麻烦一些。

来看一下步骤:1 / 2 ^1位(为了方便,下面仅用2的指数来表示位),

第1位:0.456小于位阶值0.5故为0;

2位,0.456大于位阶值0.25,该位为1,并将0.45减去0.25得0.206进下一位;

3位,0.206大于位阶值0.125,该位为1,并将0.206减去0.125得0.081进下一位;

4位,0.081大于0.0625,为1,并将0.081减去0.0625得0.0185进下一位;

5位0.0185小于0.03125,为0……

===========================

  //得到浮点尾数二进制

   double d = 0.0d;

  double d1 =0.456;

  StringBuilder sb = new StringBuilder();

  for (int i = 1; i < 19; i++) {

      d = Math.pow(2,- i);

      if(d1<d){

        sb.append(0);

      }else {

        sb.append(1);

       d1 = d1 - d;

      }

  }

  System.out.println(sb.toString());

==================================

问题出来了,即使超过尾数的最大长度23位也除不尽!这就是著名的浮点数精度问题了。不过我在这里不是要给大家讲《数值计算》,用各种方法来提高计算精度,因为那太庞杂了,恐怕我讲上一年也理不清个头绪啊。我在这里就仅把浮点数表示法讲清楚便达到目的了。

反正最后一直求也求不尽,加上前面的整数部算够24位就行了:1111011.01110100101111001。某BC问:“不是23位吗?”我:“倒,不是说过了要把第一个1去掉吗?当然要加一位喽!”

现在开始向左移小数点,大家和我一起移,众:“1、2、3……”好了,一共移了6位,6加上127得133(怎么跟教小学生似的?呵呵~),二进制表示为:10000101,符号位为……再……

不说了,越说越啰嗦,大家自己看吧:
0  10000101  11101101110100101111001
42  F6  E9  79

32位浮点数(123.456)在内存中如果存储为 79  E9  F6  42。


则先将其到序 42  F6  E9  79使其高位在前;


再将其转化为二进制:0 10000101 11101101110100101111001
最高位是符号位 0表示是正值;


接下来8位是指数位 转换为十进制再减127 结果6;


尾数部分右移6位111011.01110100101111001;


最前面添1 变为1111011.01110100101111001;


整数部分为1111011 转为十进制 123;


小数部分01110100101111001;


其中0对应2的-1次方,接下来的1对应2的-2次方:

即0*2(-1)+1*2(-2)+1*2(-3)+1*2(-4)+0*2(-5)+1*2(-6)...... ≈ 0.456

最后相加接近于0。456
结果123.456

==========================================================

Java 程序:

System.out.println("将 123.456F 浮点数转换成16进制:");

System.out.println("十进制位:"+Float.floatToIntBits(123.456f));

System.out.println("十进制位转二进制:"+Integer.toBinaryString(Float.floatToIntBits(123.456f)));

String string = Integer.toHexString(Float.floatToIntBits(123.456f)).toUpperCase();

System.out.println("十六进制:"+string);

System.out.println("十六进制转换成10进制位:"+Integer.parseInt(string, 16));

System.out.println("十进制浮点数:"+Float.intBitsToFloat(Integer.parseInt(string, 16)));

===============================================================

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Leolu007/archive/2010/05/06/5561935.aspx

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值