首页 > 解决方案 > 如何将 Uint8List 转换为 Float32List 到 List在颤振?

问题描述

我将 Dart 的typed_data库与flutter_bluetooth_serial. 后者的限制之一是它只能读取Uint8List格式数据。但是,我需要发送一堆单精度浮点数(特别是来自另一个微控制器)。我可以将数据从微控制器发送到 Flutter,但后者不能很好地解码 Uint8List。我不确定这是否是库中的错误,或者我的代码中缺少某些内容。下面显示的是旨在转换intBytes为的代码片段List<double>

Uint8List intBytes = Uint8List.fromList([63, 158, 184, 82,]);
List<double> floatList = intBytes.buffer.asFloat32List().toList();

intBytes变量表示一个四字节单精度数 (1.24...),它使用 8 位整数数组声明。然而,即使在将缓冲区视为浮点列表之后,floatBytes 似乎也无法从所述数组中获得正确的值。如果我尝试使用以下代码从第一个元素中查看值的类型

print(doubleList[0].runtimeType);

它将它作为一种int数据类型读取,但我期待一个double

标签: flutterdart

解决方案


从您的评论中:

第一个元素的值为396464455680; 一个与浮点值相差甚远的整数值1.24...

39646445568063是对字节序列, 158, 184,的 little-endian 表示的正确解释82。您显然假设它将被解释为大端单精度浮点值,但 IEEE-754 没有指定字节序。如果你反转字节,你将进入1.2400000095367432一个小端系统:

  Uint8List intBytes = Uint8List.fromList([63, 158, 184, 82].reversed.toList());
  List<double> floatList = intBytes.buffer.asFloat32List();
  print(floatList);

(顺便说一下,Float32List派生自List<double>,所以你不需要额外的.toList()调用。)

或者,您可以使用ByteData.getFloat32指定的字节序来解析字节:

  Uint8List intBytes = Uint8List.fromList([63, 158, 184, 82]);
  ByteData byteData = intBytes.buffer.asByteData();
  List<double> floatList = [
    for (var offset = 0; offset < intBytes.length; offset += 4)
      byteData.getFloat32(offset, Endian.big),
  ];
  print(floatList);

请注意,使用ByteData.getFloat32将比自己重新排序字节更健壮,因为它会使您的代码与您正在运行的平台的字节序无关。

关于:

print(doubleList[0].runtimeType);

它将它作为一种int数据类型读取,但我期待一个double

假设您的意思是floatListdoubleList在您的示例中未定义),如果您在 Dart VM 中运行该代码,则double应该打印。

但是,如果您在 Web 浏览器中运行该代码(例如,使用 DartPad 或 Flutter for Web),int将被打印出来。作为一个更简单的示例,运行:

  double d = 1.0;
  print(d.runtimeType);

在 DartPad 中也会打印int. 在 Web 上,Dart 转译为 JavaScript,为了提高效率,Dart 直接使用了一些 JavaScript 原语。JavaScript 不区分整数和浮点类型;所有数字都是双精度浮点值。因此,类型信息在往返过程中丢失也就不足为奇了。


推荐阅读