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 to read the two bytes into an int, but from there I'm not having much success expanding that out into a full floating point number. Any clues?
Asked
Active
Viewed 3,644 times
4 Answers
10
@Toji: Thanks a lot! Here a version with optimizations for NON high-end-engines like 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)
);
};
And a more complete IEEE 754 test:
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");
};
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 %

Jack G
- 4,553
- 2
- 41
- 50

Thomas Fischer
- 540
- 4
- 16
5
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:
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
}

Toji
- 33,927
- 22
- 105
- 115
-
Sorry, yeah. I goofed. That should be 'f'. I'll fix it in two seconds. – Toji Apr 17 '11 at 04:52
1
Take inspiration from jspack. A bunch of people tried similar stuff before.

zneak
- 134,922
- 42
- 253
- 328
-1
Begin reading this wikipedia article. For implementation, I'd create a lookup table. (or maybe two, one for high and low byte.
-
To the downvoter: Please take a moment to explain why! The wikipedia page in question is very informative. The lookup table suggestion maybe less so. – Toji Apr 16 '11 at 03:09
-
@Toji: Usually if you need half floats, you need to store really a lot of them, and then performance matters. – Apr 16 '11 at 12:03
-
2I'm not disputing that, and certainly I think performance is the reason they are used here. But I don't see how I two part lookup table could work for floating point numbers, and a lookup table containing 65536 values seems, umm... a little extreme? – Toji Apr 17 '11 at 04:55