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

1910

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


11
请注意,如果您从字符串表示开始,将其转换为数字并将其转换为十六进制,很容易失去精度。请参阅http://www.danvk.org/wp/2012-01-20/accurate-hexadecimal-to-decimal-conversion-in-javascript/。 - studgeek
1
这个函数正是你所需要的。 - Muhammad Musavi
30个回答

3182

使用以下方法将数字转换为十六进制字符串:

hexString = yourNumber.toString(16);

用以下方法反转该过程:

yourNumber = parseInt(hexString, 16);

57
在这种情况下,yourNum是一个十六进制字符串。例如,(255).toString(16) == 'ff' && parseInt('ff', 16) == 255。 - Prestaul
24
@Derek,我有一个心理问题,不能容忍不必要的括号... @其他所有人,yourNumber是一个变量。如果你想使用一个数字文字,则需要像(45).toString(16)这样做,但如果您是硬编码一个数字,请自己将其写成十六进制字符串... (45).toString(16)始终等于'2d',所以不要浪费CPU周期来计算它。 - Prestaul
53
“不要浪费 CPU 循环去弄清楚那个” - 这被称为过早优化。除非 JavaScript 运行在 286 上,否则我怀疑开销的重要性。此外,“45”可能是程序员需要能够识别的魔数(比如超时持续时间为秒),而“2d”,好吧,谁会认识它呢? - Dejay Clayton
86
如果您不喜欢括号,您可以使用额外的点:“42..toString(16)”。意思是将数字42转换成16进制表示形式,并且使用两个点来操作该数字。 - Thomas Watson
27
在JavaScript中,所有的数字都是浮点数。所以4242.0是相同的。但是可以省略零并写成42.。因此,如果你写42.toString(16),句点不会被视为你尝试调用一个函数,而是作为小数点。所以,要实际调用函数,你需要在小数点后面添加额外的句点。 - Thomas Watson
显示剩余16条评论

168

如果你需要处理类似于位字段或32位颜色之类的东西,那么你需要处理有符号数。JavaScript函数toString(16)会返回一个负十六进制数,这通常不是你想要的。该函数会执行一些疯狂的加法来使其成为正数。

function decimalToHexString(number)
{
  if (number < 0)
  {
    number = 0xFFFFFFFF + number + 1;
  }

  return number.toString(16).toUpperCase();
}

console.log(decimalToHexString(27));
console.log(decimalToHexString(48.6));


2
通常情况下不需要进行这种转换,因为JavaScript可以将所有32位比特字段表示为无符号数字(请参见Number.MAX_SAFE_INTEGER)。 出于同样的原因,将有符号数转换为无符号数可以写成: number = 0x100000000 + number; - Johannes Matokic
3
关于我之前评论的简短说明:虽然十六进制表示法对于小于Number.MAX_SAFE_INTEGER的数字应该是有效的,但位运算(通常用于创建32位颜色)并非如此。位运算的结果总是一个带符号的32位整数。因此,位运算结果大于等于2^31为负数,而0x100000000 | 0 === 0。 - Johannes Matokic
42
您可以使用 >>> 运算符将数字转换为无符号表示,例如 ((-3253) >>> 0).toString(16) 返回 "fffff34b" - csharpfolk
1
对于有用的补充请点“+1”,但是如果你正在将数字转换为不同的记数法,所有数字都“通常”已经是正数,否则你需要负结果。 - Carl Smith

110

以下代码将把十进制值d转换为十六进制值。它还允许您向十六进制结果添加填充。因此,默认情况下,0将变为00。

function decimalToHex(d, padding) {
    var hex = Number(d).toString(16);
    padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding;

    while (hex.length < padding) {
        hex = "0" + hex;
    }

    return hex;
}

6
这段代码无法正确处理负数。例如,使用 decimalToHex(-6, 4) 函数会返回 00-6。请进行修正。 - JonMR
3
它也有浮点数问题,但加入 Math.round() 可以解决这个问题。 (+1赞) - Michael
我正在从数组中提取数字('255,0,55'等),但.toString(16)不起作用。我只得到了相同的数字!我在前面添加了"Number"函数,现在它可以工作了!只花了大约四个小时来寻找解决方案!! - Cristofayre

75
function toHex(d) {
    return  ("0"+(Number(d).toString(16))).slice(-2).toUpperCase()
}

2
function hexRep(number, width) { return (number+Math.pow(16, precision)).toString(16).slice(-width); } - Lori
2
扩展它并不难,你只需要使用.slice(-number)来截取最后几位即可。如果你在前面添加更多的零,它也会正常工作。 - Tatarize
49
ES6 const hex = d => Number(d).toString(16).padStart(2, '0') - Ninh Pham
@NinhPham 哇哦,多么出色的回答 :) - SefaUn
"0"或"0o"是八进制前缀,对于十六进制字符串表示,应该是"0x"或"0X" - undefined

54

3
这绝对是这个问题中最有价值的回答 :) - albertjan
浏览所有问题,因为“C# 数字转十六进制”与“Javascript 数字转十六进制”产生了不同的结果。看起来 Javascript 在处理负数时存在问题。这个答案似乎是解决问题的方法。 - goamn
4
非常感谢,这对我非常有帮助!我正在使用它来处理 RGB 颜色,所以要获取 24 位的变体,请删除前两个字符(多余的 FF)- ((-2)>>>0).toString(16).substring(2) - antonyh

39

带有内边距:

function dec2hex(i) {
   return (i+0x10000).toString(16).substr(-4).toUpperCase();
}

2
@Lucas 它返回最后4个字符。 - Gabriel

24
接受的答案没有考虑到返回单个数字的十六进制代码。这很容易调整:
function numHex(s)
{
    var a = s.toString(16);
    if ((a.length % 2) > 0) {
        a = "0" + a;
    }
    return a;
}

并且

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应用程序的效率
更新:在多次测试后,我发现了一个错误(正则表达式中的双引号),所以我进行了修复。然而!经过大量的测试并阅读了almaz的帖子后,我意识到我无法使负数起作用。
进一步来说 - 我对此进行了一些阅读,由于所有的JavaScript数字都以64位字存储,无论如何 - 我尝试修改numHex代码以获得64位字。但事实证明你不能这样做。如果你将"3.14159265"作为一个数字放入一个变量中 - 你只能得到"3",因为小数部分只能通过将数字乘以十(即10.0)来访问。或者换句话说 - 0xF的十六进制值导致浮点值在进行AND运算之前被转换为整数,从而去除了小数点后的所有内容。而不是将值作为一个整体(即3.14159265)并将浮点值与0xF值进行AND运算。
因此,在这种情况下,最好的做法是将3.14159265转换为一个字符串,然后再进行转换。由于上述原因,这也使得转换负数变得容易,因为减号只需在值的前面加上0x26即可。
所以我所做的是,在确定变量包含一个数字时,只需将其转换为字符串并转换字符串。这意味着在服务器端,您需要对传入的字符串进行解码,然后确定传入的信息是否为数字。您可以通过在数字前面添加“#”和在字符字符串前面添加“ A”来轻松实现这一点。请参阅toHex()函数。
玩得开心!
经过又一年的思考,我决定对“toHex”函数(我还有一个“fromHex”函数)进行彻底改进。整个问题是“如何更高效地完成这个任务?”我决定一个转换为/从十六进制的函数不应该关心是否为小数部分,但同时应确保小数部分包含在字符串中。
然后问题变成了,“你如何知道你正在处理一个十六进制字符串?”答案很简单。使用全球已经被认可的标准前缀信息。
换句话说 - 使用“0x”。因此,现在我的toHex函数会检查是否已经存在该前缀,如果存在,它将只返回发送给它的字符串。否则,它会转换字符串、数字或其他内容。以下是修改后的toHex函数:
/////////////////////////////////////////////////////////////////////////////
//  toHex().  Convert an ASCII string to hexadecimal.
/////////////////////////////////////////////////////////////////////////////
toHex(s)
{
    var l = "0123456789ABCDEF";
    var o = "";

    if (typeof s != "string") {
        s = s.toString();
    }

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

    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 (typeof s != "string") {
        s = s.toString();
    }

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

    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,你需要将循环改为每次四个字符。但是你还需要确保字符串不能被四整除。如果可以被四整除,那么它就是一个标准的十六进制字符串。(记住字符串前面有"0x")。
一个简单的测试脚本,用来展示将-3.14159265转换为字符串后仍然是-3.14159265。
<?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()函数。
更新:在阅读下面的评论后,第一个IF语句应该在测试"s"是否为字符串之后。

我认为你还有工作要做……例如,在if( s.substr(0,2)之前放置if (typeof s != "string")可能不是你想要的。而且,我返回的结果也不是我预期的(toHex(0x1f635)会得到"0x313238353635")。我还没有进一步调查。 - ruffin
1
我认为你是错误的。你的例子使用的是十六进制字符串,而不是字符串,而是数字。因此,1f635 将以它本来的方式出现。如果你输入"0x1f635",它将会有所不同。(例如:程序将返回你发送给程序的十六进制数。) :-) - Mark Manning
第一点是你不能在非字符串上使用 substrtoLowerCase... 所以要么 typeof 需要更早出现,要么,如果你期望 toHex 在那里对非字符串抛出异常,你应该完全删除 typeof 检查。明白了吗?也就是说,如果我在没有编辑的情况下使用这里的代码,并调用 toHex(0x1f635),我会得到 Uncaught TypeError: s.substr is not a function。如果我将字符串转换提前,你是对的,数字首先转换为十进制,然后事情就会变得复杂起来。当然,这意味着如果 s 不是字符串,你不能在这里进行简单的转换。 - ruffin
1
实际上,在XP下这个很好用。Javascript已经有了许多更新,使得Javascript被强制类型转换。这会抛出异常。在XP下它只是工作。至少对我来说是这样的。在一个强制类型转换的世界中 - 放置 "if( typeof s == "string" && s.substr(0,2) == "0x"){return s;}" 是适当的。但是ox1f635仍然不是一个字符串。 :-) - Mark Manning
1
给ruffin - 你是对的。将字符串转换放在IF语句之前,该语句执行substr操作。已更正。 - undefined

21

不使用循环:

function decimalToHex(d) {
  var hex = Number(d).toString(16);
  hex = "000000".substr(0, 6 - hex.length) + hex;
  return hex;
}

// Or "#000000".substr(0, 7 - hex.length) + hex;
// Or whatever
// *Thanks to MSDN

另外,不使用需要评估的循环测试是否更好呢?

例如,不要这样写:

for (var i = 0; i < hex.length; i++){}
< p >有< /p >
for (var i = 0, var j = hex.length; i < j; i++){}

20

将一些好的想法结合起来,用于 RGB 值转换为十六进制函数(在 HTML/CSS 中添加 #):

function rgb2hex(r,g,b) {
    if (g !== undefined)
        return Number(0x1000000 + r*0x10000 + g*0x100 + b).toString(16).substring(1);
    else
        return Number(0x1000000 + r[0]*0x10000 + r[1]*0x100 + r[2]).toString(16).substring(1);
}

谢谢!我本来就想很久以前就留下评论了。这是我回答的关键。https://dev59.com/Um035IYBdhLWcg3wNdLg - Pimp Trizkit

16

限制/填充到一定数量的字符:

function decimalToHex(decimal, chars) {
    return (decimal + Math.pow(16, chars)).toString(16).slice(-chars).toUpperCase();
}

2
这将数字转换为十六进制字符串并填充前导零,非常美妙! - Gordon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接