Javascript 在 JS 中读取/写入浮点字节数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4414077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 12:19:15  来源:igfitidea点击:

Read/Write bytes of float in JS

javascriptserializationfloating-pointmathieee-754

提问by Michael Pliskin

Is there any way I can read bytes of a float value in JS? What I need is to write a raw FLOAT or DOUBLE value into some binary format I need to make, so is there any way to get a byte-by-byte IEEE 754 representation? And same question for writing of course.

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

采纳答案by KooiInc

Would this snippethelp?

请问这段代码的帮助?

@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

回答by Eric

You can do it with 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

Or another way:

或者另一种方式:

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

Not sure what browser support is like though

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

回答by Haravikk

I've created an expansion of Milos' solution that should be a bit faster, assuming TypedArrays are not an option of course (in my case I'm working with an environment where they're not available):

我已经创建了应该更快一点的 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);
}

Given an integer containing 4 bytes holding an IEEE-754 32-bit single precision float, this will produce the (roughly) correct Javascript number value without using any loops.

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

回答by kigiri

I had a similar problem, I wanted to convert any javascript number to a Buffer and then parse it back without stringifying it.

我有一个类似的问题,我想将任何 javascript 数字转换为 Buffer,然后将其解析回来而不对其进行字符串化。

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

Use example:

使用示例:

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

This works on current Node LTS (4.3.1) and up. didn't test in lower versions.

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

回答by Milo? Ra?i?

Koolinc's snippet is good if you need a solution that powerful, but if you need it for limited use you are better off writing your own code. I wrote the following function for converting a string hex representation of bytes to a float:

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

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);
}

There are detailed explanations of algorithms used to convert in both directions for all formats of floating points on wikipedia, and it is easy to use those to write your own code. Converting from a number to bytes should be more difficult because you need to normalize the number first.

维基百科上对所有格式的浮点进行双向转换的算法都有详细的解释,使用这些算法编写自己的代码很容易。从数字转换为字节应该更困难,因为您需要先对数字进行归一化。

回答by T.J. Crowder

I expect you could figure it out (blech), but I assume you're asking if there's something built-in. Not as far as I've ever heard; see sections 8.5 and 15.7 of the spec.

我希望你能弄明白(blech),但我假设你在问是否有内置的东西。不像我听说过的那样;参见规范的8.5 和 15.7 节。