如何在Java中将IEEE-11073 16位SFLOAT转换为简单浮点?
标题不言自明:如何在Java中将IEEE-11073 16位SFLOAT转换为简单浮点?您可以使用位移位。提取符号、指数和尾数,并将其移位,使其为浮点格式。您可能需要更正无穷大和NaN如何在Java中将IEEE-11073 16位SFLOAT转换为简单浮点?,java,types,floating-point,Java,Types,Floating Point,标题不言自明:如何在Java中将IEEE-11073 16位SFLOAT转换为简单浮点?您可以使用位移位。提取符号、指数和尾数,并将其移位,使其为浮点格式。您可能需要更正无穷大和NaN 正如@PretiP的回答所指出的,指数是以10为基数的,因此需要乘以或除以10的幂才能得到最终值。我找不到任何与IEEE 11073相关的浮点规范,您可能指的是a(有时也称为迷你浮点) Wikipedia对该格式进行了充分描述,可以轻松地将其转换为普通浮点。基本上,您将其分为3个字段(符号、指数、尾数)。 该标志
正如@PretiP的回答所指出的,指数是以10为基数的,因此需要乘以或除以10的幂才能得到最终值。我找不到任何与IEEE 11073相关的浮点规范,您可能指的是a(有时也称为迷你浮点) Wikipedia对该格式进行了充分描述,可以轻松地将其转换为普通浮点。基本上,您将其分为3个字段(符号、指数、尾数)。 该标志不需要转换,只需要移动到正确的位置。然后检查指数的最小值或最大值,处理特殊情况(Inf、NaN、低于正常值/非标准化)。否则,只需修正指数的偏差,然后移到正确的位置。 对于尾数,根据需要在右侧添加尽可能多的零。最后,将所有内容合并到一个int中,并使用Float.intBitsToFloat(bits)将这些位转换为普通的java浮点
从float转换的工作原理几乎相同,只是存在舍入、溢出和下溢的额外陷阱。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]+无穷大[指数0,尾数+(2^11–2)→ 0x07FE]–无穷大[指数0,尾数–(2^11–2)→ 0x0802] 保留供将来使用[指数0,尾数–(2^11–1)→ 0x0801]
此11073库的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;
}
尝试搜索“Personal Health Devices Transcoding_WP_V11”,它将引导您找到Bluetooth特殊兴趣小组的文档。在2011年10月25日/V11r00版本的文档中,第2.2节“将蓝牙特性转换为11073属性”给出了如何处理11073-20601浮点(32位)和SFLOAT(16位)数字的详细说明和示例
此文档的当前URL为
请注意,这很可能是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));
}
}
public short getExponent(短值)
{
如果(值<0)
{//如果指数应该为负
返回(字节)((值>>12)和0x0F)| 0xF0);
}
返回(短)((值>>12)和0x0F);
}
公共短尾数(短值)
{
如果((值&0x0800)!=0)
{//如果尾数应该是负数
返回(短)((值&0x0FFF)| 0xF000);
}
返回(短)(值和0x0FFF);
}
公共双解析FloatToDouble(短值)
{
//楠
如果(值==0x07FF)
{
返回Double.NaN;
}
//NRE(不适用于本决议)
else if(值==0x0800)
{
返回Double.NaN;
}
//+INF
否则如果(值==0x07FE)
{
返回双正无穷大;
}
//-INF
else if(值==0x0802)
{
返回双负无穷大;
}
//含蓄的
else if(值==0x0801)
{
返回Double.NaN;
}
其他的
{
return((double)get尾数(value))*Math.pow(10,getExponent(value));
}
}
对于那些希望在使用Javascript时转换SFLOAT的人,这里有一个简洁的库,可以实现这一点,还有更多。
如果您想添加自己的特性,只需使用addMeta函数,
defs/charMeta.js有很多例子 你能提供这种格式的引文吗?我很难找到一个规范。对于仍在寻找此规范的任何人来说,它被称为“个人健康设备代码转换白皮书”,可以从Bluetooth SIG以PDF格式提供。这一特定类型在第9页。这是其中的大部分,假定无穷大和NaN转换得到正确处理(包括NaN的信令位)。但是,您还必须处理非规范化。当偏置指数为0时,有效位字段的解释不同:隐式位为0,而不是1。必须对其进行调整,因为32位浮点中调整后的指数将不为零,因此隐式位将为1。一种调整是从32位浮点中减去隐式位(0x1p-126)的值(如果是正的,则加上负的)。很好的一点,编辑它以提及非规范化数字。SNaN不应该引起麻烦,因为java禁止信令。根据,SFLOAT格式使用十进制,而这不是半精度浮点,因此仅仅调整二进制指数是行不通的。你有例子吗?比如说69,哪个是符号、指数和尾数?非常感谢@符号为正,指数为6表示2^6,manitssa为1.000101,每个引号中,指数为基数10。仅将其转换为Java的基本两位数格式无法工作。这是新的url:。谢谢你的邀请
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));
}
}