最近在做项目的时候,老大让我用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#的方法完美的实现了步骤①的逆向,到此问题全部解决,留此文章以备自己后用。