JavaScript - 以干净的方式将字节转换为浮点数
JavaScript - Convert bytes into float in a clean way
我最近发现我可以将 Float32 转换成表示它的字节数组 - 像这样:
let number = Math.PI;
let bytes = new Uint8Array(new Float32Array([number]).buffer); // [219, 15, 73, 64]
有没有办法以干净的方式将 bytes
转换回 Float32?
Is there a way to convert bytes back into the Float32
你不需要转换它,它已经存在了!你只需要从 float32 视图中读取它。但是在您的示例中,您没有保存对 float32 视图的引用...
类型数组的工作方式与 JavaScript 中的其他数字非常不同。关键是独立地考虑缓冲区和视图——也就是说,Float32Array 和 Uint8Array 只是 views 到缓冲区(缓冲区只是一个固定大小的连续内存块,这就是为什么类型化数组是如此之快)。
在您的示例中,当您调用 new Float32Array
时,您向它传递了一个带有单个数字的数组来初始化它,但您没有向它传递一个缓冲区,这会导致它为您创建一个缓冲区适当的长度(4 字节)。当您调用 new Uint8Array
时,您传递给它的是一个缓冲区,这并不会导致它仅仅复制缓冲区,而是实际上直接使用它。下面的示例与您的示例等效,但保留了所有引用并使上述断言更加明显:
const number = Math.PI
const buffer = new ArrayBuffer(4);
const f32 = new Float32Array(buffer); // [0]
const ui8 = new Uint8Array(buffer); // [0, 0, 0, 0]
f32[0] = number;
f32 // [3.1415927410125732]
ui8 // [219, 15, 73, 64]
ui8[3] = 1;
f32 // [3.6929245196445856e-38]
ui8 // [219, 15, 73, 1]
如您所见,无需在上面 "convert",因为两个视图共享相同的缓冲区,通过一个视图进行的任何更改都会立即在另一个视图中可用。
这实际上是玩弄和理解浮点格式的好方法。还使用 ui8[i].toString(2)
获取原始二进制文件并使用 ui8[i] = parseInt('01010101', 2)
为 i 为 0-3 的每个字节设置原始二进制文件。请注意,您不能通过 f32 视图设置原始二进制文件,因为它会以数字方式解释您的数字并将其分解为有效数字和指数,但是您可能希望这样做以查看数字二进制文件如何转换为 float32 格式。
我最近发现我可以将 Float32 转换成表示它的字节数组 - 像这样:
let number = Math.PI;
let bytes = new Uint8Array(new Float32Array([number]).buffer); // [219, 15, 73, 64]
有没有办法以干净的方式将 bytes
转换回 Float32?
Is there a way to convert bytes back into the Float32
你不需要转换它,它已经存在了!你只需要从 float32 视图中读取它。但是在您的示例中,您没有保存对 float32 视图的引用...
类型数组的工作方式与 JavaScript 中的其他数字非常不同。关键是独立地考虑缓冲区和视图——也就是说,Float32Array 和 Uint8Array 只是 views 到缓冲区(缓冲区只是一个固定大小的连续内存块,这就是为什么类型化数组是如此之快)。
在您的示例中,当您调用 new Float32Array
时,您向它传递了一个带有单个数字的数组来初始化它,但您没有向它传递一个缓冲区,这会导致它为您创建一个缓冲区适当的长度(4 字节)。当您调用 new Uint8Array
时,您传递给它的是一个缓冲区,这并不会导致它仅仅复制缓冲区,而是实际上直接使用它。下面的示例与您的示例等效,但保留了所有引用并使上述断言更加明显:
const number = Math.PI
const buffer = new ArrayBuffer(4);
const f32 = new Float32Array(buffer); // [0]
const ui8 = new Uint8Array(buffer); // [0, 0, 0, 0]
f32[0] = number;
f32 // [3.1415927410125732]
ui8 // [219, 15, 73, 64]
ui8[3] = 1;
f32 // [3.6929245196445856e-38]
ui8 // [219, 15, 73, 1]
如您所见,无需在上面 "convert",因为两个视图共享相同的缓冲区,通过一个视图进行的任何更改都会立即在另一个视图中可用。
这实际上是玩弄和理解浮点格式的好方法。还使用 ui8[i].toString(2)
获取原始二进制文件并使用 ui8[i] = parseInt('01010101', 2)
为 i 为 0-3 的每个字节设置原始二进制文件。请注意,您不能通过 f32 视图设置原始二进制文件,因为它会以数字方式解释您的数字并将其分解为有效数字和指数,但是您可能希望这样做以查看数字二进制文件如何转换为 float32 格式。