【问题标题】:Converting an Array of Hexadecimal Strings to Numbers将十六进制字符串数组转换为数字
【发布时间】:2015-06-11 18:46:51
【问题描述】:

我有一个应用程序,其中服务器每秒向请求它的客户端发送大量数据。在这个数据集中有几个(大)数组,其中包含数字(在某些情况下是 16 位整数,在其他情况下是双精度浮点数)。为了减小数据包大小,我想只发送表示数字所需的字节数(16 位为 2 个字节,64 位为 8 个字节)。我知道我可以这样做:

/* Create space for 4 32 bit numbers */
var buffer = new ArrayBuffer(16);

/* Hex representation of [0, 123, 246, 369] */
buffer = ["0x0", 0x7B", "0xF6", "0x171"];

/* Actual array containing numbers above */
var int32View = new Int32Array(buffer); 

但是....我不想在所有内容前面加上“0x”(添加两个字节将使 16 位数字的大小加倍)。我想我可能遗漏了一些东西 - 有没有更好的方法来做到这一点,这样我就不需要指出字符串是数字的十六进制表示(即我可以删除“0x”)吗?

谢谢,马特

【问题讨论】:

  • 你是如何传输数据的?作为字符串还是二进制?
  • 如果你自己解析它,我想你可以做任何你想做的事情。例如,您可以省略 0x 并查找小数点以确定它是否为浮点数。或者只是在前面加上“x”并寻找它。真的,天空才是极限。
  • ["0x0", "0x7B", "0xF6", "0x171"].map(Number) == ["0", "7B", "F6", "171"].map(function(a){return parseInt(a,16);})
  • 您将无法从字符串转换浮点数的 64 位表示,因为 JS 没有 64 位整数(yet/es7)。为此,您必须使用 big-int 库(您的示例还用普通数组覆盖类型化数组)。您必须拆分这些值,然后将它们转换为类型化数组。对于浮点数,首先是一个 32 位有符号数组,使用生成的缓冲区作为 Float32 的源(64 位需要特殊处理)。
  • @Pete - 数据作为 JSON 字符串传输。我想最小化数组的大小(即我不想将 5 个字节用于可能表示为 2 的东西)。在服务器端,我可以做的是将数字转换为十六进制表示,但我不想将“0x”附加为 1)这将在计算上很昂贵,并且 2)它会影响传输的数据的大小.

标签: javascript hex typed-arrays


【解决方案1】:

您可以使用 map() 或 for 循环来处理每个值,并使用长度作为对它们进行排序的基础。

不过,请注意,您提到了 64 位浮点数。当这些从缓冲区中提取出来时,它们将是 IEEE-754 格式的 64 位整数值(即 0xXXXXXXXXXXXXXXXX)。

但是,JavaScript 只能处理 32 位值 (0xXXXXXXXX),因此您必须使用 32 位无符号数组将这些处理分成两部分,然后再添加一个 Float64Array 视图。

如果浮点值是文字,即“2.345”、“-1.33”等,那么您可以简单地在它们上使用parseFloat(str)(而不是像下面那样处理64位值)。

示例

// inserted 64-bit IEEE float of -2.3357 = 0x7b4a233ac002af83
var normArray = ["0", "7B", "F6", "7b4a233ac002af83", "171"],
    int16a = [], int32a = [],
    int16b, int32b, float64b;

normArray.map(function(entry) {
  if (entry.length > 4) {
    var high = entry.substr(0, 8),
        low = entry.substr(8, 8);
    int32a.push(parseInt(high, 16), parseInt(low, 16));
  }
  else {
    int16a.push(parseInt(entry, 16));
  }
});

// convert to typed arrays
int16b = new Int16Array(int16a);
int32b = new Uint32Array(int32a);
float64b = new Float64Array(int32b.buffer); // convert IEEE rep. to floats

document.writeln("<pre>int16  : " +
                int16b[0] + ", " + int16b[1] + ", " + int16b[2] + ", ...");
document.write("float64: " + float64b[0] + "</pre>")

【讨论】:

  • 谢谢,K3N...浮点数的好解决方案。在运行了一些测试之后,看起来使用parseInt() 并没有我想象的那么昂贵。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2019-02-12
  • 1970-01-01
相关资源
最近更新 更多