在 JavaScript 中将十六进制转换为浮点数

发布于 2024-10-18 12:23:20 字数 654 浏览 2 评论 0原文

我想将带有分数的 10 基数转换为 16 基数。

var myno = 28.5;

var convno = myno.toString(16);
alert(convno);

一切都很好。现在我想将其转换回十进制。

但现在我不能写:

var orgno = parseInt(convno, 16);
alert(orgno);

因为它不返回小数部分。

而且我不能使用 parseFloat,因为根据 MDC,parseFloat 的语法是

parseFloat(str);

如果我必须转换回 int,则不会有问题,因为 parseInt 的语法是

parseInt(str [, radix]);

那么有什么替代方案呢?

免责声明:我认为这是一个微不足道的问题,但谷歌搜索没有给我任何答案。

这个问题让我提出了上述问题。< /子>

I would like to convert a number in base 10 with fraction to a number in base 16.

var myno = 28.5;

var convno = myno.toString(16);
alert(convno);

All is well there. Now I want to convert it back to decimal.

But now I cannot write:

var orgno = parseInt(convno, 16);
alert(orgno);

As it doesn't return the decimal part.

And I cannot use parseFloat, since per MDC, the syntax of parseFloat is

parseFloat(str);

It wouldn't have been a problem if I had to convert back to int, since parseInt's syntax is

parseInt(str [, radix]);

So what is an alternative for this?

Disclaimer: I thought it was a trivial question, but googling didn't give me any answers.

This question made me ask the above question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

小傻瓜 2024-10-25 12:23:20

另一种可能性是单独解析数字,将字符串分成两部分,并在转换过程中将两部分都视为整数,然后将它们加回一起。

function parseFloat(str, radix)
{
    var parts = str.split(".");
    if ( parts.length > 1 )
    {
        return parseInt(parts[0], radix) + parseInt(parts[1], radix) / Math.pow(radix, parts[1].length);
    }
    return parseInt(parts[0], radix);
}

var myno = 28.4382;
var convno = myno.toString(16);
var f = parseFloat(convno, 16);
console.log(myno + " -> " + convno + " -> " + f);

Another possibility is to parse the digits separately, splitting the string up in two and treating both parts as ints during the conversion and then add them back together.

function parseFloat(str, radix)
{
    var parts = str.split(".");
    if ( parts.length > 1 )
    {
        return parseInt(parts[0], radix) + parseInt(parts[1], radix) / Math.pow(radix, parts[1].length);
    }
    return parseInt(parts[0], radix);
}

var myno = 28.4382;
var convno = myno.toString(16);
var f = parseFloat(convno, 16);
console.log(myno + " -> " + convno + " -> " + f);

ζ澈沫 2024-10-25 12:23:20

试试这个。

该字符串可以是具有四个字符 (0 - 255) 的原始数据(简单文本)或
长度为四个字节的十六进制字符串“0xFFFFFFFF”。

jsfiddle.net

var str = '0x3F160008';

function parseFloat(str) {
    var float = 0, sign, order, mantissa, exp,
    int = 0, multi = 1;
    if (/^0x/.exec(str)) {
        int = parseInt(str, 16);
    }
    else {
        for (var i = str.length -1; i >=0; i -= 1) {
            if (str.charCodeAt(i) > 255) {
                console.log('Wrong string parameter');
                return false;
            }
            int += str.charCodeAt(i) * multi;
            multi *= 256;
        }
    }
    sign = (int >>> 31) ? -1 : 1;
    exp = (int >>> 23 & 0xff) - 127;
    mantissa = ((int & 0x7fffff) + 0x800000).toString(2);
    for (i=0; i<mantissa.length; i+=1) {
        float += parseInt(mantissa[i]) ? Math.pow(2, exp) : 0;
        exp--;
    }
    return float*sign;
}

Try this.

The string may be raw data (simple text) with four characters (0 - 255) or
a hex string "0xFFFFFFFF" four bytes in length.

jsfiddle.net

var str = '0x3F160008';

function parseFloat(str) {
    var float = 0, sign, order, mantissa, exp,
    int = 0, multi = 1;
    if (/^0x/.exec(str)) {
        int = parseInt(str, 16);
    }
    else {
        for (var i = str.length -1; i >=0; i -= 1) {
            if (str.charCodeAt(i) > 255) {
                console.log('Wrong string parameter');
                return false;
            }
            int += str.charCodeAt(i) * multi;
            multi *= 256;
        }
    }
    sign = (int >>> 31) ? -1 : 1;
    exp = (int >>> 23 & 0xff) - 127;
    mantissa = ((int & 0x7fffff) + 0x800000).toString(2);
    for (i=0; i<mantissa.length; i+=1) {
        float += parseInt(mantissa[i]) ? Math.pow(2, exp) : 0;
        exp--;
    }
    return float*sign;
}
淡紫姑娘! 2024-10-25 12:23:20

请尝试这个:

function hex2dec(hex) {
    hex = hex.split(/\./);
    var len = hex[1].length;
    hex[1] = parseInt(hex[1], 16);
    hex[1] *= Math.pow(16, -len);
    return parseInt(hex[0], 16) + hex[1];
}

function hex2dec(hex) {
  hex = hex.split(/\./);
  var len = hex[1].length;
  hex[1] = parseInt(hex[1], 16);
  hex[1] *= Math.pow(16, -len);
  return parseInt(hex[0], 16) + hex[1];
}



// ----------
// TEST
// ----------

function calc(hex) {
  let dec = hex2dec(hex);
  msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
} 

let init="bad.a55";
inp.value=init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>

Please try this:

function hex2dec(hex) {
    hex = hex.split(/\./);
    var len = hex[1].length;
    hex[1] = parseInt(hex[1], 16);
    hex[1] *= Math.pow(16, -len);
    return parseInt(hex[0], 16) + hex[1];
}

function hex2dec(hex) {
  hex = hex.split(/\./);
  var len = hex[1].length;
  hex[1] = parseInt(hex[1], 16);
  hex[1] *= Math.pow(16, -len);
  return parseInt(hex[0], 16) + hex[1];
}



// ----------
// TEST
// ----------

function calc(hex) {
  let dec = hex2dec(hex);
  msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
} 

let init="bad.a55";
inp.value=init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>

阳光的暖冬 2024-10-25 12:23:20

我结合了 Mark 的Kent 的答案 制作一个重载的 parseFloat 函数,该函数接受基数参数(更简单、更多才多艺的):

function parseFloat(string, radix)
{
    // Split the string at the decimal point
    string = string.split(/\./);
    
    // If there is nothing before the decimal point, make it 0
    if (string[0] == '') {
        string[0] = "0";
    }
    
    // If there was a decimal point & something after it
    if (string.length > 1 && string[1] != '') {
        var fractionLength = string[1].length;
        string[1] = parseInt(string[1], radix);
        string[1] *= Math.pow(radix, -fractionLength);
        return parseInt(string[0], radix) + string[1];
    }
    
    // If there wasn't a decimal point or there was but nothing was after it
    return parseInt(string[0], radix);
}

I combined Mark's and Kent's answers to make an overloaded parseFloat function that takes an argument for the radix (much simpler and more versatile):

function parseFloat(string, radix)
{
    // Split the string at the decimal point
    string = string.split(/\./);
    
    // If there is nothing before the decimal point, make it 0
    if (string[0] == '') {
        string[0] = "0";
    }
    
    // If there was a decimal point & something after it
    if (string.length > 1 && string[1] != '') {
        var fractionLength = string[1].length;
        string[1] = parseInt(string[1], radix);
        string[1] *= Math.pow(radix, -fractionLength);
        return parseInt(string[0], radix) + string[1];
    }
    
    // If there wasn't a decimal point or there was but nothing was after it
    return parseInt(string[0], radix);
}
原来分手还会想你 2024-10-25 12:23:20

试试这个:

  1. 确定小数点后需要多少位精度。
  2. 将原始数字乘以 16 次方(例如,如果您想要两位数,则为 256)。
  3. 将其转换为整数。
  4. 根据您在步骤 1 中决定的内容手动输入小数点。

反向执行步骤即可转换回来。

  1. 取出小数点,记住它在哪里。
  2. 将十六进制转换为整数形式的十进制。
  3. 将结果除以 16 的相应幂(16^n,其中 n 是您在步骤 1 中取出的小数点后的位数)。

一个简单的例子:

将十进制23.5转换为十六进制,转换后想要小数点后一位。

23.5 x 16 = 376。

转换为十六进制 = 0x178。

底数为 16 的答案: 17.8

现在转换回小数:

去掉小数点: 0x178

转换为小数: 376

除以 16: 23.5

Try this:

  1. Decide how many digits of precision you need after the decimal point.
  2. Multiply your original number by that power of 16 (e.g. 256 if you want two digits).
  3. Convert it as an integer.
  4. Put the decimal point in manually according to what you decided in step 1.

Reverse the steps to convert back.

  1. Take out the decimal point, remembering where it was.
  2. Convert the hex to decimal in integer form.
  3. Divide the result by the the appropriate power of 16 (16^n, where n is the number of digits after the decimal point you took out in step 1).

A simple example:

Convert decimal 23.5 into hex, and want one digit after the decimal point after conversion.

23.5 x 16 = 376.

Converted to hex = 0x178.

Answer in base 16: 17.8

Now convert back to decimal:

Take out the decimal point: 0x178

Convert to decimal: 376

Divide by 16: 23.5

月下凄凉 2024-10-25 12:23:20

我不确定你想在那里解析什么十六进制格式。这是类似:“a1.2c”吗?

浮点数通常使用 IEEE 754 标准以十六进制格式存储。该标准不使用任何点(纯十六进制字母中不存在点)。相反,存在三组预定义长度的位(1 + 8 + 23 = 总共 32 位 ─ double 使用 64 位)。

我编写了以下函数来将此类数字解析为浮点数:

function hex2float(num) {
    var sign = (num & 0x80000000) ? -1 : 1;
    var exponent = ((num >> 23) & 0xff) - 127;
    var mantissa = 1 + ((num & 0x7fffff) / 0x7fffff);
    return sign * mantissa * Math.pow(2, exponent);
}

I'm not sure what hexadecimal format you wanted to parse there. Was this something like: "a1.2c"?

Floats are commonly stored in hexadecimal format using the IEEE 754 standard. That standard doesn't use any dots (which don't exist in pure hexadecimal alphabet). Instead of that there are three groups of bits of predefined length (1 + 8 + 23 = 32 bits in total ─ double uses 64 bits).

I've written the following function for parsing such a numbers into float:

function hex2float(num) {
    var sign = (num & 0x80000000) ? -1 : 1;
    var exponent = ((num >> 23) & 0xff) - 127;
    var mantissa = 1 + ((num & 0x7fffff) / 0x7fffff);
    return sign * mantissa * Math.pow(2, exponent);
}
执妄 2024-10-25 12:23:20

以下是 Mark Eirich 的答案的大小改进:

function hex2dec(hex) {
  let h = hex.split(/\./);
  return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}

function hex2dec(hex) {
  let h = hex.split(/\./);
  return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}

function calc(hex) {
  let dec = hex2dec(hex);
  msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
} 

let init = "bad.a55";
inp.value = init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>

Here is a size-improvement of Mark Eirich's answer:

function hex2dec(hex) {
  let h = hex.split(/\./);
  return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}

function hex2dec(hex) {
  let h = hex.split(/\./);
  return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}

function calc(hex) {
  let dec = hex2dec(hex);
  msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
} 

let init = "bad.a55";
inp.value = init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>

节枝 2024-10-25 12:23:20
private hexStringToFloat(hexString: string): number {
    return Buffer.from(hexString, 'hex').readFloatBE(0);
}
private hexStringToFloat(hexString: string): number {
    return Buffer.from(hexString, 'hex').readFloatBE(0);
}
执笔绘流年 2024-10-25 12:23:20

有人可能会发现这很有用。

字节到 Float32

function Int2Float32(bytes) {
    var sign = (bytes & 0x80000000) ? -1 : 1;
    var exponent = ((bytes >> 23) & 0xFF) - 127;
    var significand = (bytes & ~(-1 << 23));

    if (exponent == 128)
        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);

    if (exponent == -127) {
        if (significand === 0) return sign * 0.0;
        exponent = -126;
        significand /= (1 << 22);
    } else significand = (significand | (1 << 23)) / (1 << 23);

    return sign * significand * Math.pow(2, exponent);
}

Someone might find this useful.

bytes to Float32

function Int2Float32(bytes) {
    var sign = (bytes & 0x80000000) ? -1 : 1;
    var exponent = ((bytes >> 23) & 0xFF) - 127;
    var significand = (bytes & ~(-1 << 23));

    if (exponent == 128)
        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);

    if (exponent == -127) {
        if (significand === 0) return sign * 0.0;
        exponent = -126;
        significand /= (1 << 22);
    } else significand = (significand | (1 << 23)) / (1 << 23);

    return sign * significand * Math.pow(2, exponent);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文