如何在Javascript中将浮点数转换为其二进制表示形式(IEEE 754)? [英] How to convert a floating point number to its binary representation (IEEE 754) in Javascript?

查看:151
本文介绍了如何在Javascript中将浮点数转换为其二进制表示形式(IEEE 754)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我已经尝试手动完成,并且在某种程度上(通常的数字)有效,但是它失败了,非常小的数字(无范围检查)和特殊情况下(NaN,无穷大等):
$ b $ pre $ 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)| ((指数+127)<< 23)| ((尾数* Math.pow(2,23))和0x7FFFFF);

我重新发明了轮子吗?

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

 函数assembleFloat(sign,exponent ,尾数)
{
return(sign<< 31)| (指数<23)| (尾数);

$ b $函数floatToNumber(flt)
{
if(isNaN(flt))//特殊情况:NaN
return assembleFloat(0,0xFF ,0x1337); //对于NaN

,尾数不为零var sign =(flt <0)? 1:0;
flt = Math.abs(flt);
if(flt == 0.0)//特殊情况:+ -0
return assembleFloat(sign,0,0);

var exponent = Math.floor(Math.log(flt)/ Math.LN2);
if(exponent> 127 || exponent< -126)//特殊情况:+ -Infinity(和巨大的数字)
返回assembleFloat(sign,0xFF,0); // Mantissa是零的+ -Infinity

var mantissa = flt / Math.pow(2,exponent);
返回assembleFloat(符号,指数+ 127,(尾数* Math.pow(2,23))和0x7FFFFF);
}

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

解决方案

这是一个函数,测试它,除非它不区分-0.0和+0.0。



它基于来自 http://jsfromhell.com/classes/binary-parser ,但它专用于32位浮点数,并返回一个整数而不是字符串。我也修改它,使其更快,(略)更可读。

  //基于Jonas Raoni的代码Soares Silva 
// http://jsfromhell.com/classes/binary-parser
函数encodeFloat(number){
var n = + number,
status =(n!== n )|| n == -Infinity || n == +无限? 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; (intPart& i){
bin [ - i] = intPart%2;
while
intPart = Math.floor(intPart / 2);
}

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

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

j = lastBit + 1;
while(round&& -j> = 0){
(bin [j] =!bin [j] - 0)&& (四舍五入= 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; (j< 8){
指数+ =(n%2)<焦耳;
n>> = 1;
j ++;
}

var mantissa = 0;
n = i + 23; (; i 尾数=(尾数<1)+ bin [i]的
; $(信号?0x80000000:0)+(指数<< 23)+尾数)| b $ b} 0;
}


What's the easiest way to convert a floating point number to its binary representation in Javascript? (e.g. 1.0 -> 0x3F800000).

I have tried to do it manually, and this works to some extent (with usual numbers), but it fails for very big or very small numbers (no range checking) and for special cases (NaN, infinity, etc.):

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

Am I reinventing the wheel?

EDIT: I've improved my version, now it handles special cases.

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

I'm still not sure if this works 100% correctly, but it seems to work good enough. (I'm still looking for existing implementations).

解决方案

Here's a function that works on everything I've tested it on, except it doesn't distinguish -0.0 and +0.0.

It's based on code from http://jsfromhell.com/classes/binary-parser, but it's specialized for 32-bit floats and returns an integer instead of a string. I also modified it to make it faster and (slightly) more readable.

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

这篇关于如何在Javascript中将浮点数转换为其二进制表示形式(IEEE 754)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆