【问题标题】:Decompressing Half Precision Floats in Javascript在 Javascript 中解压缩半精度浮点数
【发布时间】:2011-08-06 09:53:31
【问题描述】:

我正在尝试使用包含大量 16 位浮点数的 javascript 读取二进制文件。相当肯定它是 IEEE 标准,小端。将这两个字节读入一个 int 非常简单,但是从那里我没有成功地将它扩展到一个完整的浮点数。有什么线索吗?

【问题讨论】:

    标签: javascript precision


    【解决方案1】:

    @Toji:非常感谢! 这是针对 V8 等非高端引擎进行优化的版本

    var pow = Math.pow;
    function decodeFloat16 (binary) {"use strict";
        var exponent = (binary & 0x7C00) >> 10,
            fraction = binary & 0x03FF;
        return (binary >> 15 ? -1 : 1) * (
            exponent ?
            (
                exponent === 0x1F ?
                fraction ? NaN : Infinity :
                pow(2, exponent - 15) * (1 + fraction / 0x400)
            ) :
            6.103515625e-5 * (fraction / 0x400)
        );
    };
    

    还有更完整的 IEEE 754 测试:

    function test() {
        var samples = [
            0x3C00, // = 1
                0xC000, // = −2
                0x7BFF, // = 6.5504 × 10^4 (max half precision)
                0x0400, // = 2^−14 ≈ 6.10352 × 10^−5 (minimum positive normal)
                0x0001, // = 2^−24 ≈ 5.96046 × 10^−8 (minimum strictly positive subnormal)
                0x0000, // = 0
                0x8000, // = −0
                0x7C00, // = Infinity
                0xFC00, // = −Infinity
                0x3555, // ≈ 0.33325... ≈ 1/3
                0x7C01  // = NaN
            ],
            i = samples.length;
        while (i--) samples[i] = decodeFloat16(samples[i]);
        return samples.join("\n");
    };
    

    与Toji原始代码的性能测试结果对比:

    • 铬 17:+30 %
    • Safari 5.1:-10 %(不要问我为什么)
    • Firefox 9:+11 %
    • IExplorer 9:+22 %
    • IExplorer 7:+14 %

    【讨论】:

      【解决方案2】:

      我最终根据维基百科页面上的信息实现了自己的解析器。它可能不是最快的,但我不太担心。这里是为那些好奇的人准备的:

      function float16_to_float(h) {
          var s = (h & 0x8000) >> 15;
          var e = (h & 0x7C00) >> 10;
          var f = h & 0x03FF;
      
          if(e == 0) {
              return (s?-1:1) * Math.pow(2,-14) * (f/Math.pow(2, 10));
          } else if (e == 0x1F) {
              return f?NaN:((s?-1:1)*Infinity);
          }
      
          return (s?-1:1) * Math.pow(2, e-15) * (1+(f/Math.pow(2, 10)));
      }
      
      function test() {
          float16_to_float(parseInt('3C00', 16)); // 1
          float16_to_float(parseInt('C000', 16)); // -2
      
          float16_to_float(parseInt('7BFF', 16)); // 6.5504 × 10^4 (Maximum half precision)
          float16_to_float(parseInt('3555', 16)); // 0.33325... ≈ 1/3
          // Works with all the test cases on the wikipedia page
      }
      

      【讨论】:

      • 对不起,是的。我搞砸了。那应该是'f'。我会在两秒钟内修复它。
      【解决方案3】:

      【讨论】:

        【解决方案4】:

        开始阅读this wikipedia article。为了实现,我会创建一个查找表。 (或者可能是两个,一个用于高字节和低字节。

        【讨论】:

        • 致反对者:请花点时间解释原因!有问题的维基百科页面信息量很大。查找表的建议可能不那么重要。
        • @Toji:通常如果你需要半个浮点数,你需要存储很多,然后性能很重要。
        • 我对此没有异议,当然我认为性能是他们在这里使用的原因。但是我看不出我的两部分查找表如何适用于浮点数,并且包含 65536 个值的查找表似乎,嗯……有点极端?
        猜你喜欢
        • 2019-11-10
        • 2020-02-03
        • 1970-01-01
        • 2011-09-03
        • 2011-10-14
        • 1970-01-01
        • 2015-07-12
        • 2013-09-19
        • 2011-11-17
        相关资源
        最近更新 更多