简体   繁体   English

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

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

[Context] [背景]
I am currently working on a probe balloon. 我目前正在研究探测气球。 My communication is restricted to messages of the 12 bytes in which I have to transmit several pieces of information. 我的通信仅限于12个字节的消息,我必须在其中传输几条信息。 (Altitude, max temperature, longitude, latitude, average acceleration). (海拔高度,最高温度,经度,纬度,平均加速度)。
The probe is based on a raspberry pi 2 b. 该探针基于树莓派2b。

[Question] [题]
I am currently building my datagram and want to store my latitude and longitude as a 32-bit double (lossy). 我目前正在构建我的数据报,并希望将我的纬度和经度存储为32位双(有损)。 Storage can be done with floating point or fixed point Are there tools to do this kind of conversion? 存储可以用浮点或固定点完成是否有工具来进行这种转换? How else can I do that? 我怎么能这样做? (in particular on the rounded party) (特别是在圆形派对上)
I initially planned to work in Java but I can migrate to python. 我最初计划在Java中工作,但我可以迁移到python。

Thank you in advance 先感谢您

Instead of using a float which is not really designed for a lat/long I suggest using a fraction. 而不是使用不是真正设计为纬度/经度的float ,我建议使用一个分数。 If you multiply by Integer.MAX_VALUE/90 for latitude and Integer.MAX_VALUE/180.0 for longitude you will get a value which uses a 32-bit value more efficiently. 如果乘以纬度的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");

prints 版画

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

in short, an int can have more than 100x the precision as it has 32-bits of precision whereas a float has a 23-bit mantissa. 简而言之, int可以具有超过100倍的精度,因为它具有32位精度,而float具有23位尾数。

For longitude, this error represents 1.7m for float and 0.94 cm using an int this way. 对于经度,此错误表示浮点数为1.7米,使用int表示为0.94厘米。

NOTE: If a 2m error is ok (more accurate than a mobile phone GPS) you might decide that float is simpler to work with. 注意:如果2m错误没问题(比手机GPS更准确),您可能会认为float更容易使用。

If you want to translate a double to 64-bits, you can use long Double.doubleToLongBits(double value) , and double Double.longBitsToDouble(long bits) to convert it back. 如果要将double转换为64位,可以使用long Double.doubleToLongBits(double value) ,并将double Double.longBitsToDouble(long bits)转换回来。

If you want to convert 32-bit values to Float values and back, the corresponding functions are floatToIntBits(...) and intBitsToFloat(...) . 如果要将32位值转换为Float值并返回,则相应的函数是floatToIntBits(...)intBitsToFloat(...)

For double to 32 bits, I'd use a 2-step conversion, converting to float first: 对于double到32位,我将使用两步转换,首先转换为float

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

And back: 然后回来:

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

Packing and unpacking directly to a buffer: 打包并直接打包到缓冲区:

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();

Of course, this creates a 20 byte buffer (5 x 32 bit floats), not a 12 byte buffer, so you'll need to figure out which values you want as 32 bits, and which you can cram into smaller space. 当然,这会创建一个20字节的缓冲区(5 x 32位浮点数),而不是12字节的缓冲区,因此您需要确定哪些值为32位,哪些值可以填入较小的空间。

Unpacking, use a DataInputStream and readFloat() . 解包,使用DataInputStreamreadFloat()

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM