我正在处理我正在尝试解码,修改和重新编码的压缩二进制数据文件。我需要能够以与解压缩相同的方式重新打包浮点值。此示例代码中的浮点值为-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;
}
}
答案 0 :(得分:3)
您的mantisse为24位且指数为7位这一事实表明您正在处理IBM style single precision floating points。当我意识到与%d
完全相同时,我在查明float4byte
为什么sgn * Math.pow(16.0, exp - 6) * mant
时遇到了一些麻烦,这正是IBM浮动工作的方式。
您编码的内容很常见IEEE-754 single precision floating points。不匹配导致了麻烦。
在IBM floating point architecture wikipedia article上,您可以找到如何将浮点数编码为IBM浮点字节的示例。
答案 1 :(得分:0)
由于@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 };
}
我认为这是正确的,似乎正在发挥作用。