首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Javascript中将浮点数转换为其二进制表示形式(IEEE754)?

如何在Javascript中将浮点数转换为其二进制表示形式(IEEE754)?
EN

Stack Overflow用户
提问于 2010-06-23 03:56:45
回答 2查看 11.5K关注 0票数 25

在Javascript中,将浮点数转换为二进制表示的最简单方法是什么?(例如1.0 -> 0x3F800000)。

我尝试过手动操作,这在某种程度上(对于通常的数字)有效,但对于非常大或非常小的数字(没有范围检查)和特殊情况(NaN、无穷大等),它都失败了:

代码语言:javascript
复制
function floatToNumber(flt)
{
    var sign = (flt < 0) ? 1 : 0;
    flt = Math.abs(flt);
    var exponent = Math.floor(Math.log(flt) / Math.LN2);
    var mantissa = flt / Math.pow(2, exponent);

    return (sign << 31) | ((exponent + 127) << 23) | ((mantissa * Math.pow(2, 23)) & 0x7FFFFF);
}

我是在重新发明轮子吗?

编辑:我改进了我的版本,现在它可以处理特殊情况。

代码语言:javascript
复制
function assembleFloat(sign, exponent, mantissa)
{
    return (sign << 31) | (exponent << 23) | (mantissa);
}

function floatToNumber(flt)
{
    if (isNaN(flt)) // Special case: NaN
        return assembleFloat(0, 0xFF, 0x1337); // Mantissa is nonzero for NaN

    var sign = (flt < 0) ? 1 : 0;
    flt = Math.abs(flt);
    if (flt == 0.0) // Special case: +-0
        return assembleFloat(sign, 0, 0);

    var exponent = Math.floor(Math.log(flt) / Math.LN2);
    if (exponent > 127 || exponent < -126) // Special case: +-Infinity (and huge numbers)
        return assembleFloat(sign, 0xFF, 0); // Mantissa is zero for +-Infinity

    var mantissa = flt / Math.pow(2, exponent);
    return assembleFloat(sign, exponent + 127, (mantissa * Math.pow(2, 23)) & 0x7FFFFF);
}

我仍然不确定这是否100%正确工作,但它似乎工作得足够好。(我仍然在寻找现有的实现)。

EN

回答 2

Stack Overflow用户

发布于 2015-10-22 21:25:17

新的技术正在使这一切变得更容易,而且可能也更具前向兼容性。我喜欢扩展内置的原型,并不是每个人都喜欢。因此,您可以随意将以下代码修改为经典过程方法:

代码语言:javascript
复制
(function() {
    function NumberToArrayBuffer() {
        // Create 1 entry long Float64 array
        return [new Float64Array([this]).buffer];
    }
    function NumberFromArrayBuffer(buffer) {
        // Off course, the buffer must be at least 8 bytes long, otherwise this is a parse error
        return new Float64Array(buffer, 0, 1)[0];
    }
    if(Number.prototype.toArrayBuffer)  {
        console.warn("Overriding existing Number.prototype.toArrayBuffer - this can mean framework conflict, new WEB API conflict or double inclusion.");
    }
    Number.prototype.toArrayBuffer = NumberToArrayBuffer;
    Number.prototype.fromArrayBuffer = NumberFromArrayBuffer;
    // Hide this methods from for-in loops
    Object.defineProperty(Number.prototype, "toArrayBuffer", {enumerable: false});
    Object.defineProperty(Number.prototype, "fromArrayBuffer", {enumerable: false});
})();

测试:

代码语言:javascript
复制
(function() {
    function NumberToArrayBuffer() {
        // Create 1 entry long Float64 array
        return new Float64Array([this.valueOf()]).buffer;
    }
    function NumberFromArrayBuffer(buffer) {
        // Off course, the buffer must be ar least 8 bytes long, otherwise this is a parse error
        return new Float64Array(buffer, 0, 1)[0];
    }
    if(Number.prototype.toArrayBuffer)  {
        console.warn("Overriding existing Number.prototype.toArrayBuffer - this can mean framework conflict, new WEB API conflict or double inclusion.");
    }
    Number.prototype.toArrayBuffer = NumberToArrayBuffer;
    Number.fromArrayBuffer = NumberFromArrayBuffer;
    // Hide this methods from for-in loops
    Object.defineProperty(Number.prototype, "toArrayBuffer", {enumerable: false});
    Object.defineProperty(Number, "fromArrayBuffer", {enumerable: false});
})();
var test_numbers = [0.00000001, 666666666666, NaN, Infinity, -Infinity,0,-0];
console.log("Conversion symethry test: ");
test_numbers.forEach(
      function(num) {
               console.log("         ", Number.fromArrayBuffer((num).toArrayBuffer()));
      }
);

console.log("Individual bytes of a Number: ",new Uint8Array((666).toArrayBuffer(),0,8));
代码语言:javascript
复制
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

票数 9
EN

Stack Overflow用户

发布于 2010-06-24 11:51:32

这里有一个函数,它可以在我测试过的所有东西上工作,除了它没有区分-0.0和+0.0。

它基于http://jsfromhell.com/classes/binary-parser中的代码,但它专门用于32位浮点数,并返回一个整数而不是字符串。我还对它进行了修改,使其速度更快,(稍微)更具可读性。

代码语言:javascript
复制
// Based on code from Jonas Raoni Soares Silva
// http://jsfromhell.com/classes/binary-parser
function encodeFloat(number) {
    var n = +number,
        status = (n !== n) || n == -Infinity || n == +Infinity ? n : 0,
        exp = 0,
        len = 281, // 2 * 127 + 1 + 23 + 3,
        bin = new Array(len),
        signal = (n = status !== 0 ? 0 : n) < 0,
        n = Math.abs(n),
        intPart = Math.floor(n),
        floatPart = n - intPart,
        i, lastBit, rounded, j, exponent;

    if (status !== 0) {
        if (n !== n) {
            return 0x7fc00000;
        }
        if (n === Infinity) {
            return 0x7f800000;
        }
        if (n === -Infinity) {
            return 0xff800000
        }
    }

    i = len;
    while (i) {
        bin[--i] = 0;
    }

    i = 129;
    while (intPart && i) {
        bin[--i] = intPart % 2;
        intPart = Math.floor(intPart / 2);
    }

    i = 128;
    while (floatPart > 0 && i) {
        (bin[++i] = ((floatPart *= 2) >= 1) - 0) && --floatPart;
    }

    i = -1;
    while (++i < len && !bin[i]);

    if (bin[(lastBit = 22 + (i = (exp = 128 - i) >= -126 && exp <= 127 ? i + 1 : 128 - (exp = -127))) + 1]) {
        if (!(rounded = bin[lastBit])) {
            j = lastBit + 2;
            while (!rounded && j < len) {
                rounded = bin[j++];
            }
        }

        j = lastBit + 1;
        while (rounded && --j >= 0) {
            (bin[j] = !bin[j] - 0) && (rounded = 0);
        }
    }
    i = i - 2 < 0 ? -1 : i - 3;
    while(++i < len && !bin[i]);
    (exp = 128 - i) >= -126 && exp <= 127 ? ++i : exp < -126 && (i = 255, exp = -127);
    (intPart || status !== 0) && (exp = 128, i = 129, status == -Infinity ? signal = 1 : (status !== status) && (bin[i] = 1));

    n = Math.abs(exp + 127);
    exponent = 0;
    j = 0;
    while (j < 8) {
        exponent += (n % 2) << j;
        n >>= 1;
        j++;
    }

    var mantissa = 0;
    n = i + 23;
    for (; i < n; i++) {
        mantissa = (mantissa << 1) + bin[i];
    }
    return ((signal ? 0x80000000 : 0) + (exponent << 23) + mantissa) | 0;
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3096646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档