将 float32 数组重新解释为 uint8 数组时字节数不匹配

Byte count mismatch when re-interpreting float32 array as uint8 array

我们打算将 float32 值数组的 JavaScript 表示更改为 uint8 字节数组。这意味着这样做可能会帮助我们更有效地通过 HTTP 请求传输数据。

为此,我们尝试过:

var vertexBuffer = ...; // Float32Array
console.log('vertex buffer =', vertexBuffer);
console.log('vertex buffer byte length = ', vertexBuffer.byteLength)
var arr = new Uint8Array(vertexBuffer);
console.log('converted to Uint8Array: ', arr);
console.log('Byte length = ', arr.byteLength);
console.log('Byte length / 4 = ', arr.byteLength / 4);

日志是:

含义

Float32Array 的大小是 84942,结果 Uint8Array 也是如此!

意味着每个 float32 值都转换为单个 uint8!这不是我们打算做的!对吧?

我们打算将每个 float32 解释为四个 uint8 值。我们怎样才能以最有效的方式做到这一点?解释的改变应该不需要任何计算吧?

It's implied that doing so might help us more efficiently transfer the data over HTTP requests.

情况并非如此,除非您确实希望将浮点值的精度截断为 8 位整数。只需通过您喜欢的任何方法发送数组的“原始数据”vertexArray.buffer(一个 ArrayBuffer)。 (当然你可以在发送之前压缩数据,如果你不喜欢的话。)

然后,您可以通过将收到的 ArrayBuffer 传递给 Float32Array 构造函数来重建 Float32Array

演示这些转换:

> arr = new Float32Array([Math.sqrt(2), Math.sqrt(3)])
// An array of 2 floats, 4 bytes each
Float32Array(2) [1.4142135381698608, 1.7320507764816284, buffer: ArrayBuffer(8), byteLength: 8, byteOffset: 0, length: 2]

> bytes = new Uint8Array(arr.buffer)
// The same floats but interpreted as 8-bit values (8 integers, 1 byte each)
Uint8Array(8) [243, 4, 181, 63, 215, 179, 221, 63, buffer: ArrayBuffer(8), byteLength: 8, byteOffset: 0, length: 8]

> bytes[1] = 123
// Modifying the byte array 
// (since an ArrayBuffer is just opaque memory, it can't be modified,
//  but we can modify the byte interpretation of it)
123

> new Float32Array(bytes.buffer)
// (this step is not strictly necessary; 
//  modifying `bytes` will have changed the underlying buffer
//  used by the original `Float32Array` since we didn't copy it)
// Reinterpreting the modified bytes as floats 
// (see how the first value has slightly changed)
Float32Array(2) [1.4178451299667358, 1.7320507764816284, buffer: ArrayBuffer(8), byteLength: 8, byteOffset: 0, length: 2]