在没有Float32Array的情况下将“float”转换为Javascript中的字节

时间:2013-04-10 20:03:44

标签: javascript floating-point type-conversion

好吧所以我是一个相当烦人的情况,我无法访问类型化的数组,如Float32Array,但仍然需要能够将Javascript数转换为字节。现在,我可以处理的整数很好,但我不知道如何为浮点值做。

我已经解决了以相反方式执行此操作的问题(将字节转换为浮点数),但是关于从float转换为字节的文档非常缺乏,因为大多数语言只是让您读取指针或具有用于处理的公共类它

理想情况下,我希望能够将浮点数转换为4字节和8字节表示,并选择使用哪一个。但是,可以简单地取一个数字并将其吐出为8字节的代码仍然很棒,因为我可以从那里自己想出32位版本。

3 个答案:

答案 0 :(得分:7)

好的,所以我实际想出来了,所以我将分享我的单精度和双精度的解决方案。现在我无法保证它们符合100%标准,但它们不需要循环,看起来效果很好:

单精度(给定十进制值输出带有二进制表示的单个32位大端整数):

function toFloat32(value) {
    var bytes = 0;
    switch (value) {
        case Number.POSITIVE_INFINITY: bytes = 0x7F800000; break;
        case Number.NEGATIVE_INFINITY: bytes = 0xFF800000; break;
        case +0.0: bytes = 0x40000000; break;
        case -0.0: bytes = 0xC0000000; break;
        default:
            if (Number.isNaN(value)) { bytes = 0x7FC00000; break; }

            if (value <= -0.0) {
                bytes = 0x80000000;
                value = -value;
            }

            var exponent = Math.floor(Math.log(value) / Math.log(2));
            var significand = ((value / Math.pow(2, exponent)) * 0x00800000) | 0;

            exponent += 127;
            if (exponent >= 0xFF) {
                exponent = 0xFF;
                significand = 0;
            } else if (exponent < 0) exponent = 0;

            bytes = bytes | (exponent << 23);
            bytes = bytes | (significand & ~(-1 << 23));
        break;
    }
    return bytes;
};

双精度(给定十进制值以big-endian顺序输出两个32位整数和二进制表示):

function toFloat64(value) {
    if ((byteOffset + 8) > this.byteLength) 
        throw "Invalid byteOffset: Cannot write beyond view boundaries.";

    var hiWord = 0, loWord = 0;
    switch (value) {
        case Number.POSITIVE_INFINITY: hiWord = 0x7FF00000; break;
        case Number.NEGATIVE_INFINITY: hiWord = 0xFFF00000; break;
        case +0.0: hiWord = 0x40000000; break;
        case -0.0: hiWord = 0xC0000000; break;
        default:
            if (Number.isNaN(value)) { hiWord = 0x7FF80000; break; }

            if (value <= -0.0) {
                hiWord = 0x80000000;
                value = -value;
            }

            var exponent = Math.floor(Math.log(value) / Math.log(2));
            var significand = Math.floor((value / Math.pow(2, exponent)) * Math.pow(2, 52));

            loWord = significand & 0xFFFFFFFF;
            significand /= Math.pow(2, 32);

            exponent += 1023;
            if (exponent >= 0x7FF) {
                exponent = 0x7FF;
                significand = 0;
            } else if (exponent < 0) exponent = 0;

            hiWord = hiWord | (exponent << 20);
            hiWord = hiWord | (significand & ~(-1 << 20));
        break;
    }

    return [hiWord, loWord];
};

对复制/粘贴中的任何错误表示道歉,代码也省略了对字节序的任何处理,尽管它很容易添加。

感谢所有人发布建议,但我最终主要依靠自己搞清楚,因为我想避免尽可能多地循环以获得速度;它仍然不是非常快,但它会做=)

答案 1 :(得分:1)

请参阅BinaryParser.encodeFloat here

答案 2 :(得分:1)

您可以像http://ysangkok.github.io/IEEE-754/index.xhtml那样使用IEEE 754的JavaScript实现。它使用Emscripten和gmp.js。