如何在JavaScript中将十进制值转换为十六进制值?


当前回答

接受的答案没有考虑返回的十六进制代码的单个数字。可通过以下方式轻松调整:

function numHex(s)
{
    var a = s.toString(16);
    if ((a.length % 2) > 0) {
        a = "0" + a;
    }
    return a;
}

and

function strHex(s)
{
    var a = "";
    for (var i=0; i<s.length; i++) {
        a = a + numHex(s.charCodeAt(i));
    }

    return a;
}

我相信上面的答案已经被其他人以这样或那样的形式发布了很多次。我将它们包装在toHex()函数中,如下所示:

function toHex(s)
{
    var re = new RegExp(/^\s*(\+|-)?((\d+(\.\d+)?)|(\.\d+))\s*$/);

    if (re.test(s)) {
        return '#' + strHex( s.toString());
    }
    else {
        return 'A' + strHex(s);
    }
}

注意,数字正则表达式来自10+有用的JavaScript正则表达式函数,以提高web应用程序的效率。

更新:在测试了几次之后,我发现了一个错误(RegExp中的双引号),所以我修复了这个错误。然而!经过相当多的测试和阅读了almaz的帖子后,我意识到我无法得到负数。

此外,我对此进行了一些阅读,因为所有JavaScript数字都存储为64位单词,无论是什么,我尝试修改numHex代码以获得64位单词。但事实证明你不能这样做。如果你把“3.14159265”作为一个数字放入一个变量中,你只能得到“3”,因为分数部分只能通过将数字重复乘以十(IE:10.0)来获得。或者换句话说,十六进制值0xF会导致浮点值在“与”运算之前转换为整数,从而删除句点后面的所有内容。而不是将该值作为一个整体(即:3.14159265),并将浮点值与0xF值进行“与”运算。

因此,在这种情况下,最好的方法是将3.14159265转换为字符串,然后再转换字符串。由于上述原因,它也使得转换负数变得容易,因为负号正好变成值前面的0x26。

所以我所做的是确定变量包含一个数字——只需将其转换为字符串并转换字符串。这对每个人都意味着,在服务器端,您需要取消对传入字符串的加热,然后确定传入的信息是数字。只需在数字前面加上一个“#”,在返回的字符串前面加上“a”,就可以很容易地做到这一点。请参见toHex()函数。

玩得高兴

经过又一年的思考,我决定“toHex”函数(我还有一个“fromHex”功能)确实需要修改。整个问题是“我如何才能更有效地执行此操作?”我决定,to/from十六进制函数不应关心某个东西是否为小数部分,但同时它应确保字符串中包含小数部分。

于是,问题变成了,“你怎么知道你在使用十六进制字符串?”。答案很简单。使用全世界公认的标准字符串前信息。

换句话说,使用“0x”。所以现在我的toHex函数看看它是否已经存在,如果已经存在-它只是返回发送给它的字符串。否则,它会转换字符串、数字等。以下是修改后的toHex函数:

/////////////////////////////////////////////////////////////////////////////
//  toHex().  Convert an ASCII string to hexadecimal.
/////////////////////////////////////////////////////////////////////////////
toHex(s)
{
    if (s.substr(0,2).toLowerCase() == "0x") {
        return s;
    }

    var l = "0123456789ABCDEF";
    var o = "";

    if (typeof s != "string") {
        s = s.toString();
    }
    for (var i=0; i<s.length; i++) {
        var c = s.charCodeAt(i);

        o = o + l.substr((c>>4),1) + l.substr((c & 0x0f),1);
    }

    return "0x" + o;
}

这是一个非常快速的函数,它考虑了个位数、浮点数,甚至可以检查用户是否正在发送一个十六进制值以再次进行十六进制运算。它只使用四个函数调用,其中只有两个在循环中。要取消十六进制值,请执行以下操作:

/////////////////////////////////////////////////////////////////////////////
//  fromHex().  Convert a hex string to ASCII text.
/////////////////////////////////////////////////////////////////////////////
fromHex(s)
{
    var start = 0;
    var o = "";

    if (s.substr(0,2).toLowerCase() == "0x") {
        start = 2;
    }

    if (typeof s != "string") {
        s = s.toString();
    }
    for (var i=start; i<s.length; i+=2) {
        var c = s.substr(i, 2);

        o = o + String.fromCharCode(parseInt(c, 16));
    }

    return o;
}

与toHex()函数一样,fromHex(()函数首先查找“0x”,然后如果传入的信息不是字符串,则将其转换为字符串。我不知道这怎么会不是一个字符串-但以防万一-我检查了一下。然后,该函数继续执行,抓取两个字符并将其转换为ASCII字符。如果您希望它转换Unicode,则需要将循环更改为每次四(4)个字符。但是,您还需要确保字符串不能被4整除。如果是-则是标准的十六进制字符串。(记住字符串前面有“0x”。)

一个简单的测试脚本显示,当转换为字符串时,-3.14159265仍然是-3.1415925。

<?php

    echo <<<EOD
<html>
    <head><title>Test</title>
        <script>
            var a = -3.14159265;
            alert( "A = " + a );
            var b = a.toString();
            alert( "B = " + b );
        </script>
    </head>
    <body>
    </body>
</html>
EOD;

?>

由于JavaScript在toString()函数方面的工作方式,所有这些以前引起问题的问题都可以消除。现在,所有字符串和数字都可以轻松转换。此外,像对象这样的东西会导致JavaScript本身生成错误。我相信这是最好的。唯一的改进是W3C只在JavaScript中包含toHex()和fromHex(()函数。

其他回答

对于任何感兴趣的人,这里有一个JSFiddle比较了这个问题的大多数答案。

下面是我最终采用的方法:

function decToHex(dec) {
  return (dec + Math.pow(16, 6)).toString(16).substr(-6)
}

此外,请记住,如果您希望将十进制转换为十六进制,以便在CSS中用作颜色数据类型,那么您可能更喜欢从十进制中提取RGB值并使用RGB()。

例如(JSFiddle):

let c = 4210330 // your color in decimal format
let rgb = [(c & 0xff0000) >> 16,  (c & 0x00ff00) >> 8,  (c & 0x0000ff)]

// Vanilla JS:
document..getElementById('some-element').style.color = 'rgb(' + rgb + ')'
// jQuery:
$('#some-element').css('color', 'rgb(' + rgb + ')')

这将#some元素的CSS颜色属性设置为rgb(64、62、154)。

任意精度

此解决方案接受输入的十进制字符串,并返回十六进制字符串。支持小数。算法

将数字拆分为符号(s)、整数部分(i)和小数部分(f),例如,对于-123.75,我们得到s=真,i=123,f=75整数部分到十六进制:如果i='0'停止取模:m=i%16(任意精度)将m转换为十六进制数字并放入结果字符串对于下一步,计算整数部分i=i/16(任意精度)小数部分计数小数n乘以k=f*16(任意精度)将k拆分为n个数字的右侧部分并将其置于f,将其余数字的左侧部分拆分为d将d转换为十六进制并添加到结果中。当结果小数位数足够时完成

//@param decStr-非负整数字符串//@param除数-正整数函数dec2Hex任意(decStr,fracDigits=0){//Helper:将任意精度数除以js数//@param decStr-非负整数字符串//@param除数-正整数函数arbDivision(decStr,除数){ //算法https://www.geeksforgeeks.org/divide-large-number-represented-string/让ans=“”;设idx=0;设temp=+decStr[idx];而(temp<除数)temp=temp*10++decStr[++idx];而(decStr.length>idx){ans+=(温度/除数)|0;temp=(temp%除数)*10++decStr[++idx];} 如果(ans.length==0)返回“0”;返回ans;} //Helper:任意精度数的计算模块//@param decStr-非负整数字符串//@param mod-正整数函数arbMod(decStr,mod){//算法https://www.geeksforgeeks.org/how-to-compute-mod-of-a-big-number/设res=0;for(设i=0;i<decStr.length;i++)res=(res*10++decStr[i])%模;回报率;} //Helper:将任意精度整数乘以js数//@param decStr-非负整数字符串//@param mult-正整数函数arbMultiply(decStr,mult){设r=“”;设m=0;对于(设i=decStr.length-1;i>=0;i-){设n=m+mult*(+decStr[i]);r=(i?n%10:n)+rm=n/10|0;}返回r;}//dec2hex算法从这里开始设h=“0123456789abcdef”;//十六进制字母表设m=decStr.match(/-?(.*?)\.(.*)?/)||decStr.匹配(/-?(.*)/);//分离符号,整数,分数设i=m[1]。替换(/^0+/,“”)。替换(/^$/,“0”);//整数部分(无符号和前导零)设f=(m[2]||'0').replace(/0+$/,'').replace(/^$/,'0');//小数部分(不带最后零)设s=decStr[0]=='-';//签名让r=“”;//后果如果(i=='0')r='0';while(i!='0'){//整数部分r=h[arbMod(i,16)]+r;i=arb除法(i,16);}如果(fracDigits)r+=“.”;设n=f.length;对于(设j=0;j<fracDigits;j++){//frac部分设k=arbMultiply(f,16);f=k切片(-n);设d=k.slice(0,k.length-n);r+=d长度?h[+d]:“0”;}return(s?'-':'')+r;}// -----------//测试// -----------让测试=[["0",2],["000",2], ["123",0],["-123",0], ["00.000",2],["255.75",5],["-255.75",5], ["127.999",32], ];console.log('输入标准能力');test.forEach(t=>{让nonArb=(+t[0]).toString(16).padEnd(17,'');设arb=dec2Hex任意(t[0],t[1]);console.log(t[0].padEnd(10,''),nonArb,arb);});//长示例(点后40位)例如=“123456789012345678901234567890.09876543210987654321”console.log(`\nLong示例:`);console.log('dec:',示例);console.log('hex:',dec2Hex任意(例如,40));

总结一下;

function toHex(i, pad) {

  if (typeof(pad) === 'undefined' || pad === null) {
    pad = 2;
  } 

  var strToParse = i.toString(16);

  while (strToParse.length < pad) {
    strToParse = "0" + strToParse;
  }

  var finalVal =  parseInt(strToParse, 16);

  if ( finalVal < 0 ) {
    finalVal = 0xFFFFFFFF + finalVal + 1;
  }

  return finalVal;
}

然而,如果不需要在结尾将其转换回整数(即颜色),那么只需确保值不是负值就足够了。

我还没有找到一个明确的答案,如果不检查它是负数还是正数,那就是使用二的补码(包括负数)。为此,我展示了一个字节的解决方案:

((0xFF + number +1) & 0x0FF).toString(16);

您可以将此指令用于任意数量的字节,只需在相应的位置添加FF。例如,设置为两个字节:

((0xFFFF + number +1) & 0x0FFFF).toString(16);

如果要将数组整数强制转换为十六进制字符串:

s = "";
for(var i = 0; i < arrayNumber.length; ++i) {
    s += ((0xFF + arrayNumber[i] +1) & 0x0FF).toString(16);
}

如果您想将数字转换为RGBA颜色值的十六进制表示,我发现这是以下几个提示的最有用组合:

function toHexString(n) {
    if(n < 0) {
        n = 0xFFFFFFFF + n + 1;
    }
    return "0x" + ("00000000" + n.toString(16).toUpperCase()).substr(-8);
}