Skip to content Skip to sidebar Skip to footer

Decompressing Half Precision Floats In Javascript

I'm trying to read a binary file with javascript that contains a lot of 16-bit floating point numbers. Fairly certain it's IEEE standard, little endian. It's pretty straightforward

Solution 1:

@Toji: Thanks a lot! Here a version with optimizations for NON high-end-engines like V8

var pow = Math.pow;
functiondecodeFloat16 (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)
    );
};

And a more complete IEEE 754 test:

function test() {
    var samples = [
        0x3C00, // = 10xC000, // = −20x7BFF, // = 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, // = 00x8000, // = −00x7C00, // = Infinity0xFC00, // = −Infinity0x3555, // ≈ 0.33325... ≈ 1/30x7C01// = NaN
        ],
        i = samples.length;
    while (i--) samples[i] = decodeFloat16(samples[i]);
    return samples.join("\n");
};

Performance test results compared with the original code from Toji:

  • Chrome 17: +30 %
  • Safari 5.1: -10 % (don't ask me why)
  • Firefox 9: +11 %
  • IExplorer 9: +22 %
  • IExplorer 7: +14 %

Solution 2:

I ended up implementing my own parser based on the information on the Wikipedia page. It's probably not the fastest out there, but I'm not too concerned about that. Here it is for those that are curious:

functionfloat16_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));
    } elseif (e == 0x1F) {
        return f?NaN:((s?-1:1)*Infinity);
    }

    return (s?-1:1) * Math.pow(2, e-15) * (1+(f/Math.pow(2, 10)));
}

functiontest() {
    float16_to_float(parseInt('3C00', 16)); // 1float16_to_float(parseInt('C000', 16)); // -2float16_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
}

Solution 3:

Take inspiration from jspack. A bunch of people tried similar stuff before.

Post a Comment for "Decompressing Half Precision Floats In Javascript"