关于JavaScript TypedArray float32的二进制格式

About the binary format of JavaScript TypedArray float32

本文关键字:二进制 格式 float32 JavaScript TypedArray 关于      更新时间:2023-09-26

我需要用JavaScript编写一个硬件模拟器。它有自己的浮点格式,所以我在JS数字和这种格式之间做了很多转换,这很慢。我有使用JavaScriptTypedArrayfloat32的想法,因为我可以直接访问形成float32浮点值的字节,该浮点值与所需格式相差不远,因此通过这种方式转换速度会快得多(使用float32的Uint8视图,只有一些移位等)。

然而,我不确定它的可移植性如何。关于TypedArray主题的各种文档都指出,float32类似于"硬件上的原生C格式"或类似的格式。但是,我能指望float32的确切二进制格式在所有运行浏览器/JS的平台上都是一样的吗?我可以猜测endiannes可能是一个问题,但如果至少没有其他差异,我可以处理它。据我所知,所使用的格式似乎是IEE754,但在一些(嗯,至少不是那么奇特…)平台上,也可以使用其他格式在JS中实现float32?

我至少可以测试x86和Apple A7 CPU,它们似乎完全相同,这很好,但也很奇怪,因为我认为这些CPU的字节顺序不同(也许至少不是浮动格式?)。然而,仅仅检查两个平台/操作系统/浏览器/任何东西都远远不是一个全球性的事实。。。

Float32Array将在内部表示基于主机系统的端序的值,通常是小端序。

是的,格式是IEEE 754(在FPU出现之前就已经存在了,它的变体涉及更多的宽度,即64位、80位等等)。JavaScript中的所有数字(Number)在内部表示为64位IEEE 754。对于类型化阵列,32位和64位的IEEE 754当然都可用。

PowerPC和68k CPU使用big-endian(应该是这样!:))。所谓的网络顺序也是大端序,许多独立于平台的文件格式都以大端序字节顺序存储(尤其是音频和图形)。大多数主流计算机都使用诸如x86之类的小端CPU。因此,在这些组合的情况下,您很可能需要处理不同的字节顺序。

要处理endianes,您可以使用DataView来代替Float32Array。

例如:

var buffer = new ArrayBuffer(10240);    // some raw byte buffer
var view = new DataView(buffer);        // flexible view supporting endianness

现在,您可以在考虑到尾数的情况下读取和写入缓冲区中的任何位置(DataView还允许从/向非对齐位置读取/写入,即如果需要,您可以将Float32值写入位置3。使用Float32/Uint32/Int16等无法做到这一点)。

浏览器将在内部转换为正确的顺序-您只需按原样提供值:

view.setFloat32(pos, 0.5);              // big-endian
view.setFloat32(pos, 0.5, false)        // big-endian
view.setFloat32(pos, 0.5, true);        // little-endian

阅读时也是如此:

var n = view.getFloat32(pos);           // big-endian
var n = view.getFloat32(pos, false)     // big-endian
var n = view.getFloat32(pos, true);     // little-endian

提示:您可以在内部使用本机Float32Array,然后使用endianes对其进行读/写。这往往会更快,但如果生成的缓冲区的端序与主机系统不同,则需要在最后使用DataView进行转换:

var f32 = new Float32Array(buffer);     // or use a size
f32[0] = 0.5;

然后确保你有big-endian表示:

var view = new DataView(f32.buffer);
var msbVal = view.getFloat32(0):        // returns 32-bit repres. in big-endian

希望能提供一些意见!如果你想让我详细阐述一下,就向我提出一些问题。