【问题标题】:About the binary format of JavaScript TypedArray float32关于 JavaScript TypedArray float32 的二进制格式
【发布时间】:2014-11-19 10:30:04
【问题描述】:

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

但是,我不确定它的便携性如何。关于 TypedArray 主题的各种文档指出,float32 类似于“该硬件上的本机 C 格式”等。但是我可以期望 float32 的确切二进制格式在运行某些浏览器/JS 的所有平台上都是相同的吗?我可以猜测字节序可能是一个问题,但如果至少没有其他差异,我可以处理这个问题。据我所知,使用的格式似乎是 IEE754,但在某些(嗯,至少不是那么奇特...)平台上,可以使用其他格式在 JS 中实现 float32?

我至少可以测试 x86 和 Apple A7 CPU,看起来它们是一样的,这很好,但也很奇怪,因为我认为这些 CPU 的字节顺序不同(至少可能不是浮动格式?)。然而,仅仅检查两个平台/操作系统/浏览器/任何东西,这远非全球真理......

【问题讨论】:

    标签: javascript typedarray


    【解决方案1】:

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

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

    PowerPC 和 68k CPU 使用大端序(它应该是这样的!:))。所谓网络顺序也是big-endian,很多平台无关的文件格式都是用big-endian字节顺序存储的(尤其是音频和图形)。大多数主流计算机使用 little-endian CPU,例如 x86。因此,在结合使用这些的情况下,您很可能必须处理不同的字节顺序。

    要处理字节顺序,您可以使用 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,然后使用字节序对其进行读/写。这往往会更快,但如果结果缓冲区的字节序与主机系统不同,则需要在最后使用 DataView 进行转换:

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

    然后确保你有大端表示:

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

    希望提供一些意见!如果您希望我详细说明某些部分,请向我提出问题。

    【讨论】:

      猜你喜欢
      • 2012-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      • 1970-01-01
      • 2020-12-03
      相关资源
      最近更新 更多