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

时间:2012-07-19 15:34:44

标签: java types floating-point

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

7 个答案:

答案 0 :(得分:7)

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位值包含4位指数   基数10,后跟12位尾数。每个都是二进制补码   形成。指定特殊值表示以下内容: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]

答案 1 :(得分:6)

这个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;
}

答案 2 :(得分:2)

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

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

答案 3 :(得分:2)

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

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

请注意,这可能与Petri P.上面提到的文档相同。

答案 4 :(得分:1)

即使这篇文章有点陈旧,我只想根据this 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));
    }
}

答案 5 :(得分:0)

对于那些希望在使用Javascript时转换SFLOAT的人,这里有一个简洁的库,它可以完成更多工作。 https://github.com/bluetoother/ble-packet

如果您想添加自己的特征,只需使用addMeta函数, defs / charMeta.js有很多示例!

答案 6 :(得分:-2)

我找不到任何与IEEE 11073相关的浮动规范,可能意味着Half precision float(有时也称为Minifloat)。

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

浮点数的转换几乎相同,只是存在舍入,溢出和下溢的额外缺陷。