【问题标题】:How to get the actual bytes of a javascript 64bit float如何获取 javascript 64 位浮点数的实际字节
【发布时间】:2017-07-24 20:50:36
【问题描述】:

我一直在尝试研究如何在 JavaScript 中使用类型化数组,但对我来说还没有点击。我不明白如何正确读取/写入“视图”。

var a = 23453.342;

现在假设我想将它存储在 Float64Array 类型数组中

view[0] = ??? //how do I copy the bytes that represent variable a into here.

还假设我想将 JavaScript 内部的整数 123456 存储为 64 位浮点数:

var i = 123456;

但我想把它当作一个 4 字节整数来存储。

var buff = new ArrayBuffer(4);
var view = new UInt32Array(buff);

view[0] = ???; //how do i determine and write the 4 bytes that would represent the value of i.

那么在这两种情况下,一旦我能够在那里写入数据,我如何将其读回 JavaScript 中的局部变量。

【问题讨论】:

  • 您可以查看我的this answer,它显示了允许您查看所有位的功能,我的this post 也非常详细地描述了这些数字是如何存储的。但您的问题似乎是关于类型化数组视图的工作原理,而不是How to get the actual bytes of a javascript 64bit float
  • 您了解类型化数组视图的工作原理吗?

标签: javascript arrays node.js typed-arrays


【解决方案1】:

当你创建一个特定类型的TypedArray 时,像这样说Int8Array

let my = new Int8Array(1);

并为其赋值,如下所示:

my[0] = 123456;

执行基于on the this table 的转换。因此,对于Int8Array,使用方法ToInt8,最后一步是:

...
让 int8bit 为 int 模 2^8。
如果 int8bit ≥ 2^7,则返回 int8bit − 2^8,否则返回 int8bit。

所以,如果我们运行这些步骤

Let int8bit be 123456 modulo 2^8 // 64
64 < 2^7 -> return int8bit, which is 64

所以64 是你应该期待的:

console.log(my[0]); // 64

如果您对实际的位顺序感兴趣,请查看this answer 了解算法或查看本文了解details of floating point

【讨论】:

  • 我已经看过您多次引用的表格,但我完全忽略了转换操作,它在您分配值时会自动执行。谢谢,那是我理解中缺少的。
  • @axawire,不客气。从另一个答案的赞成票数量来看,我的印象是我误解了你的问题。感谢您的接受。
【解决方案2】:

如果您的值小于 Typed Array 单元而不是将值存储到数组中,例如您有 23453.342 并使用 Float64,那么只需将其放入数组中

var view = new Float64Array(1);
view[0] = 23453.342;

现在,如果您想将一个数字转换为其单独的字节,例如一个 32 位数字并获得组成它的 4 个字节,您可以使用两个 TypedArray 视图。将你的值放入高位数组,并从低位数组中读取字节。

//The argument passed to ArrayBuffer constructor 
//is number of Bytes the buffer should be
var buff = new ArrayBuffer(4);
//Since buffer was made for 4 bytes, this view can read/store 1 32bit value
var view = new Uint32Array(buff);
//buffer still has 4 bytes, so this view can read/store 4 8bit values
var view2 = new Uint8Array(buff);

view[0] = 123456;
console.log(view2);

如果您想手动获取字节,或者无法访问更高单位的类型数组,则可以使用位移位和按位 AND 运算符来获取各个字节

var i = 123456;

var buff = new ArrayBuffer(4);
var view = new Uint32Array(buff);
var view2 = new Uint8Array(buff);

view2[0] = i & 0x000000FF;
view2[1] = (i & 0x0000FF00) >> 8;
view2[2] = (i & 0x00FF0000) >> 16;
view2[3] = (i & 0xFF000000) >> 24; 

console.log( view2, view[0] );

至于取回值,在使用两个类型数组的情况下,您只需读取目标单元的数组。在这种情况下从 Uint32Array 读取

var buff = new ArrayBuffer(4);
var view = new Uint32Array(buff);
var view2 = new Uint8Array(buff);
view2[0] = 64, view2[1] = 226, view2[2] = 1, view2[3] = 0;
var i = view[0];
console.log(i);

同样,如果你想使用位移方式,你需要从较小的类型数组中移动每个字节,然后将它们按位或在一起。

var buff = new ArrayBuffer(4);
var view = new Uint8Array(buff);
view[0] = 64, view[1] = 226, view[2] = 1, view[3] = 0;
var i = 0;
i |= view[3] << 24;
i |= view[2] << 16;
i |= view[1] << 8;
i |= view[0];
console.log(i);

【讨论】:

  • 谢谢您,非常感谢您的详细回复。我希望我能接受 2 个答案,但另一个答案完成了我的理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2021-10-06
  • 2014-01-27
  • 1970-01-01
  • 2022-11-01
相关资源
最近更新 更多