在JS中读/写浮点字节

时间:2010-12-10 23:03:15

标签: javascript serialization floating-point math ieee-754

有什么方法可以在JS中读取浮点值的字节?我需要的是将原始FLOAT或DOUBLE值写入我需要制作的二进制格式,那么有没有办法获得逐字节的IEEE 754表示?当然,写作也是一样的问题。

6 个答案:

答案 0 :(得分:38)

您可以使用typed arrays

执行此操作
var buffer = new ArrayBuffer(4);
var intView = new Int32Array(buffer);
var floatView = new Float32Array(buffer);

floatView[0] = Math.PI
console.log(intView[0].toString(2)); //bits of the 32 bit float

或另一种方式:

var view = new DataView(new ArrayBuffer(4));
view.setFloat32(0, Math.PI);
console.log(view.getInt32(0).toString(2)); //bits of the 32 bit float

不确定浏览器支持是什么样的

答案 1 :(得分:7)

我已经创建了Milos解决方案的扩展,它应该更快一些,假设TypedArrays当然不是一个选项(在我的情况下,我正在使用它们不可用的环境):

function Bytes2Float32(bytes) {
    var sign = (bytes & 0x80000000) ? -1 : 1;
    var exponent = ((bytes >> 23) & 0xFF) - 127;
    var significand = (bytes & ~(-1 << 23));

    if (exponent == 128) 
        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);

    if (exponent == -127) {
        if (significand == 0) return sign * 0.0;
        exponent = -126;
        significand /= (1 << 22);
    } else significand = (significand | (1 << 23)) / (1 << 23);

    return sign * significand * Math.pow(2, exponent);
}

给定一个包含4个字节的整数,保存IEEE-754 32位单精度浮点数,这将产生(大致)正确的Javascript数值而不使用任何循环。

答案 2 :(得分:3)

this snippet会有帮助吗?

@ Kevin Gadd

var parser = new BinaryParser
  ,forty = parser.encodeFloat(40.0,2,8) 
  ,twenty = parser.encodeFloat(20.0,2,8);  
console.log(parser.decodeFloat(forty,2,8).toFixed(1));   //=> 40.0
console.log(parser.decodeFloat(twenty,2,8).toFixed(1));  //=> 20.0

答案 3 :(得分:3)

如果你需要一个功能强大的解决方案,Koolinc的代码是好的,但是如果你需要它用于有限的使用,你最好编写自己的代码。我编写了以下函数,用于将字节的字符串十六进制表示形式转换为float:

function decodeFloat(data) {
    var binary = parseInt(data, 16).toString(2);
    if (binary.length < 32) 
        binary = ('00000000000000000000000000000000'+binary).substr(binary.length);
    var sign = (binary.charAt(0) == '1')?-1:1;
    var exponent = parseInt(binary.substr(1, 8), 2) - 127;
    var significandBase = binary.substr(9);
    var significandBin = '1'+significandBase;
    var i = 0;
    var val = 1;
    var significand = 0;

    if (exponent == -127) {
        if (significandBase.indexOf('1') == -1)
            return 0;
        else {
            exponent = -126;
            significandBin = '0'+significandBase;
        }
    }

    while (i < significandBin.length) {
        significand += val * parseInt(significandBin.charAt(i));
        val = val / 2;
        i++;
    }

    return sign * significand * Math.pow(2, exponent);
}

对维基百科上所有浮点格式的双向转换算法都有详细说明,并且很容易使用这些算法来编写自己的代码。从数字转换为字节应该更加困难,因为您需要首先规范化数字。

答案 4 :(得分:2)

我遇到了类似的问题,我想将任何javascript编号转换为Buffer,然后再将其解析而不进行字符串化。

function numberToBuffer(num) {
  const buf = new Buffer(8)
  buf.writeDoubleLE(num, 0)
  return buf
}

使用示例:

// convert a number to buffer
const buf = numberToBuffer(3.14)
// and then from a Buffer
buf.readDoubleLE(0) === 3.14

这适用于当前的Node LTS(4.3.1)及更高版本。没有在较低版本中测试。

答案 5 :(得分:0)

我希望你能搞清楚(blech),但我猜你在问是否有内置的东西。不是我听过的;见the spec的第8.5和15.7节。