我正在处理一个打包的二进制数据文件,我正在尝试解码,修改和重新编码。我需要能够以与解包相同的方式重新打包浮点值。此示例代码中的浮点值为 -1865.0。我需要在byte4float
中做什么,以便返回的四个字节与我开始时相同,即 (C3 74 90 00 (。
public class HelloWorld {
public static void main(String[] args) {
byte[] bytes = {(byte) 0xC3,(byte) 0X74,(byte) 0X90,(byte) 0X00 };
byte newbytes[] = new byte[4];
float f;
f = float4byte (bytes[0], bytes[1], bytes[2], bytes[3]);
System.out.println("VAL Bytes : " + f);
// Now see if we can reverse it
// NOT Working
newbytes = byte4float(f);
System.out.println ("TO Bytes: "+String.format("%02X ", newbytes[0])+
String.format("%02X ", newbytes[1])+String.format("%02X ", newbytes[2])+String.format("%02X ", newbytes[3]));
}
/**
* Convert four bytes into a float value. Byte parameters
*
* @param a highest byte
* @param b higher byte
* @param c lower byte
* @param d lowest byte
*
* @return float value
*/
private static float float4byte(byte a, byte b, byte c, byte d)
{
int sgn, mant, exp;
System.out.println ("IN Byte : "+String.format("%02X ", a)+
String.format("%02X ", b)+String.format("%02X ", c)+String.format("%02X ", d));
mant = ( b &0xFF) << 16 | (c & 0xFF ) << 8 | ( d & 0xFF);
if (mant == 0) return 0.0f;
sgn = -(((a & 128) >> 6) - 1);
exp = (a & 127) - 64;
return (float) (sgn * Math.pow(16.0, exp - 6) * mant);
}
/**
* Convert float value into a four bytes.
*
* @param f float value to convert
*
* @return byte[0] highest byte, byte[1] higher byte, byte[2] lower byte, byte[3] lowest byte
*/
private static byte[] byte4float(float f)
{
byte newbytes[] = new byte[4];
int bits = Float.floatToIntBits(f);
newbytes[0] = (byte)(bits & 0xff);
newbytes[1] = (byte)((bits >> 8) & 0xff);
newbytes[2] = (byte)((bits >> 16) & 0xff);
newbytes[3] = (byte)((bits >> 24) & 0xff);
return newbytes;
}
}
您的尾数是 24 位,指数是 7 位这一事实表明您正在处理 IBM 风格的单精度浮点数。我很难弄清楚为什么float4byte
会sgn * Math.pow(16.0, exp - 6) * mant
,当我意识到这与sgn * Math.pow(16, exp) * (mant / Math.pow(2, 24)
相同时,这正是IBM浮动的工作方式。
您正在编码的是常见的 IEEE-754 单精度浮点数。不匹配导致麻烦。
在 IBM 浮点架构维基百科文章中,您可以找到如何将浮点数编码为 IBM 浮点字节的示例。
由于@halfbit输入和一些小的更改,此例程会将 IEEE 754 float 转换为 IBM float。
public static byte[] byte4float(float f) {
assert !Float.isNaN(f);
// see also JavaDoc of Float.intBitsToFloat(int)
int bits = Float.floatToIntBits(f);
int s = (bits >> 31) == 0 ? 1 : -1;
int e = (bits >> 23) & 0xFF;
int m = (e == 0) ? (bits & 0x7FFFFF) << 1 : (bits& 0x7FFFFF) | 0x800000;
int exp = (e - 150) / 4 + 6;
int mant;
int mantissaShift = (e - 150) % 4; // compensate for base 16
if (mantissaShift >= 0) mant = m >> mantissaShift;
else mant = m >> (Math.abs(mantissaShift));
if (mant > 0xFFFFFFF) { mant >>= 4; exp++; } // loose of precision */
byte a = (byte) ((1 - s) << 6 | (exp + 64));
return new byte[]{ a, (byte) (mant >> 16), (byte) (mant >> 8), (byte) mant };
}
我认为这是正确的,并且似乎正在起作用。