将 double 转换为 32 位表示(和反向过程)

Transform a double into a 32-bit representation (and reverse procedure)

[上下文]
我目前正在研究探测气球。我的通信仅限于 12 字节的消息,我必须在其中传输几条信息。 (海拔高度、最高温度、经度、纬度、平均加速度)。
探针基于a raspberry pi 2 b.

[问题]
我目前正在构建我的数据报,并希望将我的纬度和经度存储为 32 位双精度(有损)。存储可以用浮点数或定点数来完成 有没有工具可以进行这种转换?我还能怎么做? (特别是圆方)
我最初计划在 Java 工作,但我可以迁移到 python。

提前致谢

如果要将 double 转换为 64 位,可以使用 long Double.doubleToLongBits(double value), and double Double.longBitsToDouble(long bits) 将其转换回来。

如果要将32位值转换为Float值并返回,对应的函数是floatToIntBits(...)intBitsToFloat(...)

对于 double 到 32 位,我会使用两步转换,首先转换为 float

double val = ...;
int bits = Float.floatToIntBits( (float) val );

返回:

int bits = ...;
double val = (double) Float.intBitsToFloat(bits);

直接打包和解包到缓冲区:

ByteArrayOutputStream baos = new ByteArrayOutputStream(20);
DataOutputStream dos = new DataOutputStream( ... );
dos.writeFloat( altitude );
dos.writeFloat( max_temperature );
dos.writeFloat( longitude );
dos.writeFloat( latitude );
dos.writeFloat( average_acceleration);
byte[] data = baos.toByteArray();

当然,这会创建一个 20 字节缓冲区(5 x 32 位浮点数),而不是 12 字节缓冲区,因此您需要确定哪些值是您想要的 32 位,哪些可以塞入更小 space.

解包,使用DataInputStreamreadFloat().

ByteArrayInputStream bais = ...
DataInputStream dis = new DataInputStream(bais);
altitude = dis.readFloat();
max_temperature = dis.readFloat();
...etc...

我建议不要使用并非真正为 lat/long 设计的 float,而是使用分数。如果您将纬度乘以 Integer.MAX_VALUE/90,将经度乘以 Integer.MAX_VALUE/180.0,您将得到一个更有效地使用 32 位值的值。

float lat = 90f;
System.out.println("precision using float: " + (lat - Math.nextDown(lat)) + " degrees");
double ratio = Integer.MAX_VALUE / 90.0;
int val2 = (int) Math.round(90 * ratio);
System.out.println("precision using int: " + 1 / ratio + " degrees");

打印

precision using float: 7.6293945E-6 degrees
precision using int: 4.190951587721217E-8 degrees

简而言之,int 的精度可以超过 100 倍,因为它具有 32 位精度,而 float 具有 23 位尾数。

对于经度,此错误表示浮动为 1.7m,使用 int 表示为 0.94 厘米。

注意:如果 2 米的误差没问题(比移动 phone GPS 更准确),您可能会认为 float 更易于使用。