如何将IEEE-11073 16位SFLOAT转换为Java中的简单浮点数?

标题不言自明:如何将IEEE-11073 16位SFLOAT转换为Java中的简单浮点数?

你可以使用位移。 提取符号,指数和尾数并将它们移位,使它们处于浮点格式。 您可能需要更正Infinity和NaN。

由于@PretiP的回答指出指数是10,所以你需要乘以或除以10的幂来得到最终值。

IEEE-11073不属于公共领域,但您可以在蓝牙个人健康档案中找到足够的信息。 谷歌完整规格#11073-2060。 以下是来自蓝牙个人健康转码纸的复制粘贴:

以下信息在ISO / IEEE标准中定义。 11073-2060™1-2008 [1]。 SFLOAT类型数据类型定义为表示类型中不是整数的数值。 SFLOAT类型定义为具有12位尾数和4位指数的16位值。 有关SFLOAT类型的详尽定义,请参见[1]的附录F.8。 该数据类型定义如下:指数尾数大小4位12位

16位浮点型; 整数类型只是一个占位符

SFLOAT-Type :: = INT-U16 16位值包含一个基数为10的4位指数,后跟一个12位尾数。 每个都是二进制forms。 分配特殊值来表示以下内容:NaN [指数0,尾数+(2 ^ 11 -1)→0x07FF] NRes [指数0,尾数 – (2 ^ 11)→0x0800] + INFINITY [指数0,尾数+( 2 ^ 11 -2)→0x07FE] – INFINITY [指数0,尾数 – (2 ^ 11 -2)→0x0802]保留供将来使用[指数0,尾数 – (2 ^ 11 -1)→0x0801]

这个11073库有C代码可以做到:

https://github.com/signove/antidote/blob/master/src/util/bytelib.c

应该不难转换为Java。

double read_sfloat(ByteStreamReader *stream, int *error) { intu16 int_data = read_intu16(stream, error); if (*error) return 0; intu16 mantissa = int_data & 0x0FFF; int8 expoent = int_data >> 12; if (expoent >= 0x0008) { expoent = -((0x000F + 1) - expoent); } float output = 0; if (mantissa >= FIRST_S_RESERVED_VALUE && mantissa <= MDER_S_NEGATIVE_INFINITY) { output = reserved_float_values[mantissa - FIRST_S_RESERVED_VALUE]; } else { if (mantissa >= 0x0800) { mantissa = -((0x0FFF + 1) - mantissa); } double magnitude = pow(10.0f, expoent); output = (mantissa * magnitude); } return output; } 

样板代码:

 typedef enum { MDER_S_POSITIVE_INFINITY = 0x07FE, MDER_S_NaN = 0x07FF, MDER_S_NRes = 0x0800, MDER_S_RESERVED_VALUE = 0x0801, MDER_S_NEGATIVE_INFINITY = 0x0802 } ReservedSFloatValues; static const intu32 FIRST_S_RESERVED_VALUE = MDER_S_POSITIVE_INFINITY; intu16 read_intu16(ByteStreamReader *stream, int *error) { intu16 ret = 0; if (stream && stream->unread_bytes > 1) { ret = ntohs(*((uint16_t *) stream->buffer_cur)); stream->buffer_cur += 2; stream->unread_bytes -= 2; } else { if (error) { *error = 1; } ERROR("read_intu16"); } return ret; } 

尝试搜索“Personal Health Devices Transcoding_WP_V11”,它将引导您访问蓝牙特别兴趣小组的文档。 在2011年10月25日/ V11r00版本的文档中,第2.2节“将蓝牙特征转换为11073属性”给出了如何处理11073-20601 FLOAT(32位)和SFLOAT(16位)数字的详细说明和示例。

该文档的当前URL是https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=242961

请注意,这可能与Petri P.在上面引用的文档相同。

即使这篇文章有点陈旧,我只想发布我的解决方案,基于这个 java文件。

 public short getExponent(short value) { if (value < 0) { // if exponent should be negative return (byte) (((value >> 12) & 0x0F) | 0xF0); } return (short) ((value >> 12) & 0x0F); } public short getMantissa(short value) { if ((value & 0x0800) != 0) { // if mantissa should be negative return (short) ((value & 0x0FFF) | 0xF000); } return (short) (value & 0x0FFF); } public double parseSFLOATtoDouble(short value) { // NaN if (value == 0x07FF) { return Double.NaN; } // NRes (not at this resolution) else if (value == 0x0800) { return Double.NaN; } // +INF else if (value == 0x07FE) { return Double.POSITIVE_INFINITY; } // -INF else if (value == 0x0802) { return Double.NEGATIVE_INFINITY; } // Reserved else if (value == 0x0801) { return Double.NaN; } else { return ((double) getMantissa(value)) * Math.pow(10, getExponent(value)); } } 

我找不到任何与IEEE 11073相关的浮点规范,你可能意味着半精度浮点数 (有时也称为Minifloat)。

在维基百科中充分描述了该格式,以便将其轻松转换为普通浮点数。 基本上,你将它分成3个字段(符号,指数,尾数)。 标志不需要转换,只需转移到正确的位置即可。 然后检查指数是否为MIN或MAX值,处理特殊情况(Inf,NaN,subnormals / denormalized)。 否则只需纠正指数的偏差并转移到正确的位置。 对于尾数,根据需要在右侧添加尽可能多的零。 最后将所有内容放在一起,并使用Float.intBitsToFloat(位)将这些位转换为普通的java浮点数。

浮动的转换工作几乎相同,只有圆角,溢出和下溢的额外缺陷。