一场关于Float.floatToIntBits(value)引发的血案

    最近在做项目的时候,老大让我用UDP协议接受一段数据,并且将byte[]中的数据进行转化,得到相对应的数值。

    UDP数据接收到了,在进行转化这一步骤的时候遇到了一点困难,从byte[]中取其中的四个,转换成为一个float值,我当时没有反应过来,就找老大要了他发过来数据的源码,然后就发现了如下代码:

          步骤①int intValue = Float.floatToIntBits(value);
          步骤②for (int i = 0; i < 4; i++) {  
             bytes[i+offset] = reserve?((byte) (intValue >> (24 - i * 8))):((byte) (intValue >> (i * 8)));  
          } 

然后想着,逆向转换回去就ok了啊。所以就向无所不知的度娘动了手,确实看到了很多关于float与byte[]的转换。但是,看到了一个跟我这个比较相合的文章,链接:https://blog.csdn.net/weixin_34234721/article/details/92955751。

附带一点基础知识:float占四个字节,一个字节8位,所以是32位。byte占一个字节,所以是8位。想要使用byte表示一个完整的float,则byte[]数组长度为4.

目前已经完成了步骤②的逆向,还差步骤①,然后就被这个java自带的方法给困住了大约一两天的样子。

下面是我查到的部分:

老规矩先上链接:https://bbs.csdn.net/topics/110073831

一、public static int floatToIntBits(float value)

根据 IEEE 754 的浮点“单一形式”中的位布局,返回指定浮点值的表示形式。 
第 31 位(掩码 0x80000000 选定的位)表示浮点数字的符号。第 30-23 位(掩码 0x7f800000 选定的位)表示指数。第 22-0 位(掩码 0x007fffff 选定的位)表示浮点数字的有效位数(有时也称为尾数)。 
如果参数为正无穷大,则结果为 0x7f800000。 
如果参数为负无穷大,则结果为 0xff800000。 
如果参数为 NaN,则结果为 0x7fc00000。 
在所有情况下,结果都是一个整数,在将其赋予 intBitsToFloat(int) 方法时,将生成一个与 floatToIntBits 的参数相同的浮点值(除所有 NaN 值被折叠成一个“规范的”NaN 值之外)。 

另外需要知道的是,float类型占用4个字节,从最低位(最右边)到最高位(最左边)的编号是从0-31。这样的话,上面的解释就容易看懂了。也就是说,转换成的32个0、1字符串中,31号表示符号,30-23表示指数,22-0表示尾数。

二、按照IEEE 754标准,32位浮点数在计算机中二进制存储形式共三部分:S(1位,符号) E(8位,阶码) M(23位,尾数)
给你举个例子吧,Float.floatToIntBits(20.5f)按照如下方式计算:
20.59D=10100.1B=1.01001*2^4B 指数e=4
S=0-->正数  E=4+127=131D=10000011B-->真实指数e变成阶码E时需加127  M=01001B
则32位2进制存储形式为:0 10000011 01001000000000000000000
转换成10进制即1101266944

注:学习链接:https://www.pediy.com/kssd/pediy06/pediy6610.htm

但是上面的内容并没有让我找到解决办法,虽然了解了许多知识。真正让我解决问题的是这篇文章的内容:

链接:http://blog.sina.com.cn/s/blog_56795ce20102w5ah.html

java:

int i = Float.intBitsToFloat(132.0232f); //1124337136

float f = Float.floatToRawIntBits(i); //132.0232

 

c++:

inline float intBitsToFloat(int i)

{

   union

   {

      int i;

      float f;

    } u;

    u.i = i;

    return u.f;

}

 

inline int floatToRawIntBits(float f)

{

   union

    {

    int i;

    float f;

    } u;

    u.f = f;

    return u.i;

}

 

C#

       public static float intBitsToFloat(int v)

       {

           byte[] buf = BitConverter.GetBytes(v);

           return BitConverter.ToSingle(buf, 0);

       }

 

       public static int floatToRawIntBits(float v)

       {

           byte[] buf = BitConverter.GetBytes(v);

           return BitConverter.ToInt32(buf, 0);

       }

 

C# 虽然没有union,可以自己来实现,挺有意思。

       [StructLayout(LayoutKind.Explicit, Size = 8)]

       public struct Float

       {

          [FieldOffset(0)]

           int i;

          [FieldOffset(0)]

           float f;

 

           public static int floatToRawIntBits(float f)

           {

              Float u;

              u.i = 0;

              u.f = f;

              return u.i;

           }

           public static float intBitsToFloat(int i)

           {

              Float u;

              u.f = 0;

              u.i = i;

              return u.f;

           }

       };

借去文章中写的C#的方法完美的实现了步骤①的逆向,到此问题全部解决,留此文章以备自己后用。

你可能感兴趣的:(一场关于Float.floatToIntBits(value)引发的血案)