JavaScript 浮点数与二进制之间的转换

862 阅读1分钟

二进制转浮点数

单精度

binary_to_float(data){
    let buf = new Uint8Array(data);
    buf.reverse();
    let buf32 =  new Float32Array(buf.buffer);
    return buf32[0];
}

双精度

binary_to_double(data) {
    let buf = new Uint8Array(data);
    buf.reverse();
    let buf64 = new Float64Array(buf.buffer);
    return buf64[0];
}

浮点数转二进制

单精度

float_to_binary(data) 
{
    var str = Number(data).toString();		//单精度浮点数转为字符串表示(十进制)
    var hexStr = this.get_float_hex(str);	//十进制字符串表示转为十六进制字符串表示
    var bin = new Uint8Array(4);
    for(let i=0,j=0;i<4;i++,j+=2)
    {
    	//将每个字节中的二进制数换算成十进制数,存到ArrayBuffer中
        let dec = parseInt(hexStr[j],16)*16 + parseInt(hexStr[j+1],16);	
        bin[i] = dec;
    }
    return bin;
}

get_float_hex(decString)
{
    var dec = decString;	//浮点数的十进制字符串
    var sign;
    var signString;
    var decValue = parseFloat(Math.abs(decString));	//获取浮点数的绝对值
    if (decString.toString().charAt(0) == '-')
    {
        sign = 1;	//若为负数,符号位为1
        signString = "1";
    }
    else
    {
        sign = 0;	//若为正数,符号位为0
        signString = "0";
    }
    if (decValue==0)	//对于0的特殊处理
    {
        fraction = 0;
        exponent = 0;
    }
    else
    {
        var exponent = 127;	//单精度浮点数的偏移值为127
        if (decValue>=2)	//若浮点数>=2,就不断除2,同时指数不断增加,直到浮点数小于2
        {
            while (decValue>=2)
            {
                exponent++;
                decValue /= 2;
            }
        }
        else if (decValue<1)	//若浮点数<1,就不断乘2,同时指数不断减少,直到浮点数大于1或指数为0
        {
            while (decValue < 1)
            {
                exponent--;
                decValue *= 2;
                if (exponent ==0)
                    break;
            }
        }
        if (exponent!=0) decValue-=1; else decValue /= 2;	//若指数不为0,取小数部分,否则除以2

    }
    var fractionString = this.DecToBinTail(decValue, 23);	//取23位尾数
    var exponentString = this.DecToBinHead(exponent, 8);	//取8位阶码
    return this.Right('00000000'+parseInt(signString + exponentString + fractionString, 2).toString(16),8);
}
DecToBinTail(dec, pad)
{
    var bin = "";
    var i;
    for (i = 0; i < pad; i++)
    {
        dec *= 2;
        if (dec>= 1)
        {
            dec -= 1;
            bin += "1";
        }
        else
        {
            bin += "0";
        }
    }
    return bin;
}

DecToBinHead(dec,pad)
{
    var bin="";
    var i;
    for (i = 0; i < pad; i++)
    {
        bin = (parseInt(dec % 2).toString()) + bin;
        dec /= 2;
    }
    return bin;
}

Right(String, Length)
{ 
    if (String == null) 
        return (false); 
    var dest = ''; 
    for (var i = (String.length - 1); i >= 0; i--) 
        dest = dest + String.charAt(i); 
    String = dest; 
    String = String.substr(0, Length); 
    dest = ''; 
    for (var i = (String.length - 1); i >= 0; i--) 
        dest = dest + String.charAt(i); 
    return dest; 
}

双精度

double_to_binary(data)
{
    var str = Number(data).toString();
    var hexStr = this.get_double_hex(str);
    var bin = new Uint8Array(8);
    for(let i=0,j=0;i<8;i++,j+=2)
    {
        let dec = parseInt(hexStr[j],16)*16 + parseInt(hexStr[j+1],16);
        bin[i] = dec;
    }
    return bin;
}

get_double_hex(decString)
{
    var dec = decString;
    var sign;
    var signString;
    var decValue = parseFloat(Math.abs(decString));
    if (decString.toString().charAt(0) == '-')
    {
        sign = 1;
        signString = "1";
    }
    else
    {
        sign = 0;
        signString = "0";
    }
    if (decValue==0)
    {
        fraction = 0;
        exponent = 0;
    }
    else
    {
        var exponent = 1023;	//双精度浮点数偏移值为1023
        if (decValue>=2)
        {
            while (decValue>=2)
            {
                exponent++;
                decValue /= 2;
            }
        }
        else if (decValue<1)
        {
            while (decValue < 1)
            {
                exponent--;
                decValue *= 2;
                if (exponent ==0)
                    break;
            }
        }
        if (exponent!=0) decValue-=1; else decValue /= 2;

    }
    var fractionString = this.DecToBinTail(decValue, 52);	//取52位尾数
    var exponentString = this.DecToBinHead(exponent, 11);	//取11位阶码
    var doubleBinStr = signString + exponentString + fractionString;
    var doubleHexStr = "";
    for(let i=0,j=0;i<8;i++,j+=8)
    {
        let m = 3-(j%4);
        let hexUnit = doubleBinStr[j]*Math.pow(2,m) + doubleBinStr[j+1]*Math.pow(2,m-1) + doubleBinStr[j+2]*Math.pow(2,m-2) + doubleBinStr[j+3]*Math.pow(2,m-3);
        let hexDecade = doubleBinStr[j+4]*Math.pow(2,m) + doubleBinStr[j+5]*Math.pow(2,m-1) + doubleBinStr[j+6]*Math.pow(2,m-2) + doubleBinStr[j+7]*Math.pow(2,m-3);
        doubleHexStr = doubleHexStr + hexUnit.toString(16) + hexDecade.toString(16);
    }
    return doubleHexStr;
}

DecToBinTail(dec, pad)
{
    var bin = "";
    var i;
    for (i = 0; i < pad; i++)
    {
        dec *= 2;
        if (dec>= 1)
        {
            dec -= 1;
            bin += "1";
        }
        else
        {
            bin += "0";
        }
    }
    return bin;
}

DecToBinHead(dec,pad)
{
    var bin="";
    var i;
    for (i = 0; i < pad; i++)
    {
        bin = (parseInt(dec % 2).toString()) + bin;
        dec /= 2;
    }
    return bin;
}

Right(String, Length)
{ 
    if (String == null) 
        return (false); 
    var dest = ''; 
    for (var i = (String.length - 1); i >= 0; i--) 
        dest = dest + String.charAt(i); 
    String = dest; 
    String = String.substr(0, Length); 
    dest = ''; 
    for (var i = (String.length - 1); i >= 0; i--) 
        dest = dest + String.charAt(i); 
    return dest; 
}

【参考文章】
JavaScript实现浮点数转十六进制