8

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

我已经解决了以另一种方式(字节转换为浮点)的问题,但是关于从浮点转换为字节的文档非常稀缺,因为大多数语言只是让您读取指针或具有处理它的通用类。

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

4

3 回答 3

8

好的,所以我实际上想通了,所以我将分享我的单精度和双精度解决方案。现在我不能保证它们 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;
};

双精度(给定一个十进制值输出两个 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];
};

对复制/粘贴中的任何错误表示歉意,代码也省略了对字节顺序的任何处理,尽管添加起来相当容易。

感谢大家提出建议,但我最终还是靠自己解决了问题,因为我想尽可能避免循环以提高速度;它仍然不是非常快,但它会做=)

于 2013-04-16T17:23:34.387 回答
1

请参阅 BinaryParser.encodeFloat此处

于 2013-04-10T20:37:49.510 回答
1

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

于 2014-01-16T17:04:18.683 回答