Распаковка половинной точности в Javascript - PullRequest
4 голосов
/ 15 апреля 2011

Я пытаюсь прочитать двоичный файл с JavaScript, который содержит много 16-битных чисел с плавающей запятой. Совершенно уверен, что это стандарт IEEE, little endian. Довольно просто прочитать два байта в целое число, но оттуда я не добьюсь большого успеха, расширив это до полного числа с плавающей запятой. Любые подсказки?

Ответы [ 4 ]

7 голосов
/ 10 января 2012

@ Тодзи: Большое спасибо!Вот версия с оптимизацией для NON мощных двигателей, таких как 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:

  • Chrome 17: +30%
  • Safari 5.1: -10% (не спрашивайте меня, почему)
  • Firefox 9: +11%
  • IExplorer 9: +22%
  • IExplorer 7: +14%
5 голосов
/ 16 апреля 2011

В итоге я реализовал свой собственный парсер на основе информации на странице Википедии. Это, вероятно, не самый быстрый, но я не слишком обеспокоен этим. Вот для любопытных:

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
}
2 голосов
/ 15 апреля 2011
0 голосов
/ 15 апреля 2011

Начните читать эту статью в Википедии . Для реализации я бы создал таблицу соответствия. (или может быть два, один для старшего и младшего байта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...