← 返回文章列表

进制转换其实很直观:二进制、十六进制与颜色代码

进制入门

核心思想:按权展开

任何进制的值 = 每位数字 × 基数的位权之和。二进制 1011 = 1×8 + 0×4 + 1×2 + 1×1 = 11。十六进制用 A–F 表示 10–15,所以 0xFF = 15×16 + 15 = 255。理解这一点,转换就只是机械计算。

为什么程序员爱十六进制

1 位十六进制恰好对应 4 位二进制,一个字节(8 位)正好写成 2 个十六进制字符。内存地址、字节序列、颜色都因此用它:#FF5733 = R:255, G:87, B:51——三组十六进制就是三个颜色通道的强度。

常见的坑

  1. 前导零丢失:"007" 被解析成数字 7,转回字符串就变了;
  2. 大数精度丢失:超过 JavaScript 的安全整数(2^53)后精度不可靠,要按字符串处理或用 BigInt;
  3. 浮点不能精确表示:0.1 在二进制中是无限循环小数,进制转换只对整数部分精确,小数部分处理时注意舍入规则。

常用数值对照

十进制二进制八进制十六进制
10101012A
2551111 1111377FF
1024100 0000 00002000400
655351111 1111 1111 1111177777FFFF

代码示例

// 解析:第二个参数是进制
parseInt('FF', 16);         // 255
Number.parseInt('1010', 2); // 10

// 输出:toString(进制)
(255).toString(16);         // "ff"
(10).toString(2);           // "1010"

// 颜色通道转十六进制(每通道补足两位)
'#' + [255, 87, 51].map(v => v.toString(16).padStart(2, '0')).join('');
// => "#ff5733"

三个必须知道的限制

  1. 前导零会丢:"007" 解析成 7,再转回来就少两位——编号、ID 类数据请按字符串处理;
  2. 大整数会失真:超过 Number.MAX_SAFE_INTEGER(2^53−1)后精度不可靠,需要 BigInt 或字符串;
  3. 小数只能近似:0.1 在二进制中是无限循环小数,转换仅保证整数部分精确。

延伸问题

为什么颜色用 6 位十六进制?每两位表示一个 0–255 的通道值,R/G/B 各两位正好 6 位,且无损对应一个字节。十六进制一定更短吗?表示同一数值时是的——基数越大,所需位数越少。

实战案例:三个进制相关的坑

  1. “端口号转 16 进制对不上”:十进制 255 是 FF,别把“进制转换”和“字节拆分”混淆。
  2. “大整数末尾几位不准”:JavaScript 数字精度约 2^53,超长整数要用字符串或 BigInt 处理。
  3. “二进制掩码算错”:先把掩码转十进制核对位与,再决定取哪几位,避免肉眼数 0/1 出错。

常见问题(FAQ)

支持小数吗?当前支持整数;小数可先按比例放大为整数再换算。负号会保留吗?会,所有进制下都保留符号。最高支持多少进制?36 进制(用满 0-9 与 a-z)。结果会丢精度吗?不会,基于 BigInt 精确运算。

动手试试:进制转换、颜色转换

工程中的常见使用场景

进制转换看似基础,但在具体场景中很容易出错,关键在于理解每个场景需要的是什么。

  1. 权限位与掩码:文件权限、网络掩码与功能开关常以八进制或二进制表示。阅读时应逐位对照含义,而不是把整体当作一个十进制数字看待。
  2. 颜色与标识:颜色与哈希常以十六进制展示,注意大小写不区分,但长度必须严格符合预期,长度不符通常意味着数据被截断或补零。
  3. 协议字段:网络协议与硬件寄存器常以固定宽度表示数值,转换时必须补齐前导零到指定宽度,否则解析方会读错字段。
  4. 短链接与编码:把自增编号转成更高进制可以缩短展示长度,但要注意字符集选择与大小写敏感问题,避免产生歧义。
  5. 大整数与精度:超出安全整数范围的数值必须按字符串处理,转换过程也不能经过浮点数,否则末尾几位会被静默改写。

验证习惯

转换结果建议反向校验一次:把结果再转回原进制,确认与输入完全一致。对关键数据还应校验长度与取值范围,单靠肉眼比对很容易漏掉一位之差。

工具与人为误差

进制转换出错几乎都源于手工操作:抄错一位、遗漏前导零、混淆进制前缀。应尽量通过工具或代码完成转换,并把结果纳入自动化校验。人工只负责判断结果是否符合业务预期,而不是负责计算本身。