如何将 Java double 转换为 byte[],将 byte[] 转换为 double(IEEE 754 双精度二进制浮点格式)
How to convert Java double to byte[], and byte[] to double (IEEE 754 double-precision binary floating-point format)
我有 3 种方法(1 种功能性(double to byte[]),一种返回意外值(byte[] to double),1 种功能性但执行许多操作以使用 Hex to double 的方法) ).
性能是最重要的,所以如果你有更高效的代码,请分享。
函数方法从double转换为byte[] getFloat64(11.27d) returns byte[]=hex string "40268A3D70A3D70A"
:
public static byte[] getFloat64(double value)
{
final byte[] float64Bytes = new byte[8];
long double64Long=Double.doubleToLongBits(value);
float64Bytes[0] = (byte)((double64Long >> 56) & 0xff);
float64Bytes[1] = (byte)((double64Long >> 48) & 0xff);
float64Bytes[2] = (byte)((double64Long >> 40) & 0xff);
float64Bytes[3] = (byte)((double64Long >> 32) & 0xff);
float64Bytes[4] = (byte)((double64Long >> 24) & 0xff);
float64Bytes[5] = (byte)((double64Long >> 16) & 0xff);
float64Bytes[6] = (byte)((double64Long >> 8) & 0xff);
float64Bytes[7] = (byte)((double64Long >> 0) & 0xff);
return float64Bytes;
}
从这个 byte[] 返回不正确的 double 值到 double 方法(调用 getFloat64(getFloat64(11.27d)) returns 9.338087023E-315):
public static double getFloat64(byte[] bytes)
{
return Double.longBitsToDouble((long)((bytes[0] & 0xFF) << 56)
| ((bytes[1] & 0xFF) << 48)
| ((bytes[2] & 0xFF) << 40)
| ((bytes[3] & 0xFF) << 32)
| ((bytes[4] & 0xFF) << 24)
| ((bytes[5] & 0xFF) << 16)
| ((bytes[6] & 0xFF) << 8)
| ((bytes[7] & 0xFF) << 0));
}
最终方法returns正确答案调用getFloat64("40268A3D70A3D70A")returns11.27:
public double getFloat64(String hex_double)
{
long longBits = Long.valueOf(hex_double,16).longValue();
return Double.longBitsToDouble(longBits);
}
中间方法有什么问题?为什么返回 11.27 不像上一个方法那样?
问题是 (bytes[0] & 0xFF)
仍然是一个 32 位整数值。如果将 32 位值向左移动 56 位,Java 将移动 56 % 32 = 24
位而不是 56 位。
您首先需要将该值提升为 64 位长,然后再对其进行位移。一种方法是使用长值 (0xFFL
) &
。任何整数文字(通常具有 int
类型,因此是 32 位)都可以通过向其附加 L
或 l
来转换为长文字。
更正后的代码:
public static double getFloat64(byte[] bytes)
{
return Double.longBitsToDouble(((bytes[0] & 0xFFL) << 56)
| ((bytes[1] & 0xFFL) << 48)
| ((bytes[2] & 0xFFL) << 40)
| ((bytes[3] & 0xFFL) << 32)
| ((bytes[4] & 0xFFL) << 24)
| ((bytes[5] & 0xFFL) << 16)
| ((bytes[6] & 0xFFL) << 8)
| ((bytes[7] & 0xFFL) << 0));
}
ob-JLS 参考:Java Language Specification 15.9:
If the promoted type of the left-hand operand is int
, only the five
lowest-order bits of the right-hand operand are used as the shift
distance. It is as if the right-hand operand were subjected to a
bitwise logical AND operator &
(§15.22.1) with the mask value 0x1f
(0b11111). The shift distance actually used is therefore always in the
range 0 to 31, inclusive.
我有 3 种方法(1 种功能性(double to byte[]),一种返回意外值(byte[] to double),1 种功能性但执行许多操作以使用 Hex to double 的方法) ).
性能是最重要的,所以如果你有更高效的代码,请分享。
函数方法从double转换为byte[] getFloat64(11.27d) returns byte[]=hex string "40268A3D70A3D70A"
:
public static byte[] getFloat64(double value)
{
final byte[] float64Bytes = new byte[8];
long double64Long=Double.doubleToLongBits(value);
float64Bytes[0] = (byte)((double64Long >> 56) & 0xff);
float64Bytes[1] = (byte)((double64Long >> 48) & 0xff);
float64Bytes[2] = (byte)((double64Long >> 40) & 0xff);
float64Bytes[3] = (byte)((double64Long >> 32) & 0xff);
float64Bytes[4] = (byte)((double64Long >> 24) & 0xff);
float64Bytes[5] = (byte)((double64Long >> 16) & 0xff);
float64Bytes[6] = (byte)((double64Long >> 8) & 0xff);
float64Bytes[7] = (byte)((double64Long >> 0) & 0xff);
return float64Bytes;
}
从这个 byte[] 返回不正确的 double 值到 double 方法(调用 getFloat64(getFloat64(11.27d)) returns 9.338087023E-315):
public static double getFloat64(byte[] bytes)
{
return Double.longBitsToDouble((long)((bytes[0] & 0xFF) << 56)
| ((bytes[1] & 0xFF) << 48)
| ((bytes[2] & 0xFF) << 40)
| ((bytes[3] & 0xFF) << 32)
| ((bytes[4] & 0xFF) << 24)
| ((bytes[5] & 0xFF) << 16)
| ((bytes[6] & 0xFF) << 8)
| ((bytes[7] & 0xFF) << 0));
}
最终方法returns正确答案调用getFloat64("40268A3D70A3D70A")returns11.27:
public double getFloat64(String hex_double)
{
long longBits = Long.valueOf(hex_double,16).longValue();
return Double.longBitsToDouble(longBits);
}
中间方法有什么问题?为什么返回 11.27 不像上一个方法那样?
问题是 (bytes[0] & 0xFF)
仍然是一个 32 位整数值。如果将 32 位值向左移动 56 位,Java 将移动 56 % 32 = 24
位而不是 56 位。
您首先需要将该值提升为 64 位长,然后再对其进行位移。一种方法是使用长值 (0xFFL
) &
。任何整数文字(通常具有 int
类型,因此是 32 位)都可以通过向其附加 L
或 l
来转换为长文字。
更正后的代码:
public static double getFloat64(byte[] bytes)
{
return Double.longBitsToDouble(((bytes[0] & 0xFFL) << 56)
| ((bytes[1] & 0xFFL) << 48)
| ((bytes[2] & 0xFFL) << 40)
| ((bytes[3] & 0xFFL) << 32)
| ((bytes[4] & 0xFFL) << 24)
| ((bytes[5] & 0xFFL) << 16)
| ((bytes[6] & 0xFFL) << 8)
| ((bytes[7] & 0xFFL) << 0));
}
ob-JLS 参考:Java Language Specification 15.9:
If the promoted type of the left-hand operand is
int
, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator&
(§15.22.1) with the mask value0x1f
(0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.