Dart 将 IEEE-11073 32 位 FLOAT 转换为简单的双精度数
Dart Convert IEEE-11073 32-bit FLOAT to a simple double
我在处理这些低级字节和数字方面没有太多经验,所以我来这里寻求帮助。我在我的 Flutter 应用程序中连接了一个蓝牙温度计,并且根据他们的文档,我得到了一组格式如下的数字。 I'm attempting to convert these numbers to a plain temperature double, but can't figure out how. This is the "example" the company gives me. 但是,当我的温度计读数为 98.5 时,我得到的响应是 [113, 14, 0, 254]
的数组
感谢您的帮助!
IEEE-11073 是医疗设备中常用的格式。你引用的 table 里面有你解码数字的所有内容,尽管一开始可能很难破译。
让我们以您的第一个示例为例:0xFF00016C
。这是一个 32 位数字,第一个字节是指数,最后三个字节是尾数。两者都以 2s 补码表示形式编码:
- 指数,
0xFF
,在 2 的补码中,这是数字 -1
- 尾数,
0x00016C
,在 2 的补码中,这是数字 364
(如果您不太确定数字如何以 2 的补码编码,请将其作为一个单独的问题提出。)
我们接下来要做的是确保它不是 "special" 值,正如您 table 中所规定的那样。由于您的指数不是 0
(而是 -1
),我们知道您没问题。所以,不需要特殊处理。
由于这个值并不特殊,所以它的数值就是:mantissa * 10^exponent
。因此,我们有:364*10^-1 = 36.4
,如您的示例所示。
你的第二个例子是相似的。指数是 0xFE
,也就是 2 的补码中的数字 -2
。尾数为0x000D97
,十进制为3479
。同样,指数不为 0,因此不需要特殊处理。所以你有:3479*10^-2 = 34.79
.
你说 98.5
值,你得到字节数组 [113, 14, 0, 254]
。让我们看看我们是否能理解这一点。你的字节数组,用十六进制写成:[0x71, 0x0E, 0x00, 0xFE]
。我猜你以 "reverse" 顺序接收这些字节,所以作为 32 位十六进制,这实际上是 0xFE000E71
.
我们以类似的方式进行:指数再次为 -2
,因为 0xFE
是您使用 8 位以 2 的补码形式编写 -2
的方式。 (见上文。)尾数是 0xE71
,等于 3697
。所以,这个数字是 3697*10^-2 = 36.97
.
您声称这实际上是 98.5
。我最好的猜测是您正在以华氏度阅读它,而您的设备正在以摄氏度报告。如果您计算一下,您会发现 36.97C = 98.55F
已经足够接近了。我不确定您是如何获得 98.5
数字的,但是对于这样的设备,此结果似乎在您可以预期的精度范围内。
希望对您有所帮助!
这是我用来在我们的 flutter 应用程序中将 sfloat16 转换为 double in dart 的东西。
double sfloat2double(ieee11073) {
var reservedValues = {
0x07FE: 'PositiveInfinity',
0x07FF: 'NaN',
0x0800: 'NaN',
0x0801: 'NaN',
0x0802: 'NegativeInfinity'
};
var mantissa = ieee11073 & 0x0FFF;
if (reservedValues.containsKey(mantissa)){
return 0.0; // basically error
}
if ((ieee11073 & 0x0800) != 0){
mantissa = -((ieee11073 & 0x0FFF) + 1 );
}else{
mantissa = (ieee11073 & 0x0FFF);
}
var exponent = ieee11073 >> 12;
if (((ieee11073 >> 12) & 0x8) != 0){
exponent = -((~(ieee11073 >> 12) & 0x0F) + 1 );
}else{
exponent = ((ieee11073 >> 12) & 0x0F);
}
var magnitude = pow(10, exponent);
return (mantissa * magnitude);
}
我在处理这些低级字节和数字方面没有太多经验,所以我来这里寻求帮助。我在我的 Flutter 应用程序中连接了一个蓝牙温度计,并且根据他们的文档,我得到了一组格式如下的数字。
感谢您的帮助!
IEEE-11073 是医疗设备中常用的格式。你引用的 table 里面有你解码数字的所有内容,尽管一开始可能很难破译。
让我们以您的第一个示例为例:0xFF00016C
。这是一个 32 位数字,第一个字节是指数,最后三个字节是尾数。两者都以 2s 补码表示形式编码:
- 指数,
0xFF
,在 2 的补码中,这是数字-1
- 尾数,
0x00016C
,在 2 的补码中,这是数字364
(如果您不太确定数字如何以 2 的补码编码,请将其作为一个单独的问题提出。)
我们接下来要做的是确保它不是 "special" 值,正如您 table 中所规定的那样。由于您的指数不是 0
(而是 -1
),我们知道您没问题。所以,不需要特殊处理。
由于这个值并不特殊,所以它的数值就是:mantissa * 10^exponent
。因此,我们有:364*10^-1 = 36.4
,如您的示例所示。
你的第二个例子是相似的。指数是 0xFE
,也就是 2 的补码中的数字 -2
。尾数为0x000D97
,十进制为3479
。同样,指数不为 0,因此不需要特殊处理。所以你有:3479*10^-2 = 34.79
.
你说 98.5
值,你得到字节数组 [113, 14, 0, 254]
。让我们看看我们是否能理解这一点。你的字节数组,用十六进制写成:[0x71, 0x0E, 0x00, 0xFE]
。我猜你以 "reverse" 顺序接收这些字节,所以作为 32 位十六进制,这实际上是 0xFE000E71
.
我们以类似的方式进行:指数再次为 -2
,因为 0xFE
是您使用 8 位以 2 的补码形式编写 -2
的方式。 (见上文。)尾数是 0xE71
,等于 3697
。所以,这个数字是 3697*10^-2 = 36.97
.
您声称这实际上是 98.5
。我最好的猜测是您正在以华氏度阅读它,而您的设备正在以摄氏度报告。如果您计算一下,您会发现 36.97C = 98.55F
已经足够接近了。我不确定您是如何获得 98.5
数字的,但是对于这样的设备,此结果似乎在您可以预期的精度范围内。
希望对您有所帮助!
这是我用来在我们的 flutter 应用程序中将 sfloat16 转换为 double in dart 的东西。
double sfloat2double(ieee11073) {
var reservedValues = {
0x07FE: 'PositiveInfinity',
0x07FF: 'NaN',
0x0800: 'NaN',
0x0801: 'NaN',
0x0802: 'NegativeInfinity'
};
var mantissa = ieee11073 & 0x0FFF;
if (reservedValues.containsKey(mantissa)){
return 0.0; // basically error
}
if ((ieee11073 & 0x0800) != 0){
mantissa = -((ieee11073 & 0x0FFF) + 1 );
}else{
mantissa = (ieee11073 & 0x0FFF);
}
var exponent = ieee11073 >> 12;
if (((ieee11073 >> 12) & 0x8) != 0){
exponent = -((~(ieee11073 >> 12) & 0x0F) + 1 );
}else{
exponent = ((ieee11073 >> 12) & 0x0F);
}
var magnitude = pow(10, exponent);
return (mantissa * magnitude);
}