【发布时间】:2011-08-06 09:53:31
【问题描述】:
我正在尝试使用包含大量 16 位浮点数的 javascript 读取二进制文件。相当肯定它是 IEEE 标准,小端。将这两个字节读入一个 int 非常简单,但是从那里我没有成功地将它扩展到一个完整的浮点数。有什么线索吗?
【问题讨论】:
标签: javascript precision
我正在尝试使用包含大量 16 位浮点数的 javascript 读取二进制文件。相当肯定它是 IEEE 标准,小端。将这两个字节读入一个 int 非常简单,但是从那里我没有成功地将它扩展到一个完整的浮点数。有什么线索吗?
【问题讨论】:
标签: javascript precision
@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原始代码的性能测试结果对比:
【讨论】:
我最终根据维基百科页面上的信息实现了自己的解析器。它可能不是最快的,但我不太担心。这里是为那些好奇的人准备的:
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
}
【讨论】:
【讨论】:
开始阅读this wikipedia article。为了实现,我会创建一个查找表。 (或者可能是两个,一个用于高字节和低字节。
【讨论】: