进制间的转换

进制间的转换

进制间的转换问题

数字是可以用不同的进制来表示的,他们只是表示的方式不同,但是其内容却是一样的,选择不同的方式来表示数字的原因可能是工程原因,比如说二进制在机器中的实现,也可能是使人易读,比如十进制,也有可能是结合二者比如十六进制颜色。既然表示内容一样,只是表示方法不同,那么就可以使用一些手段,将他们互相转换。

其他进制转换为十进制

进制中数的表示方法可以简单的描述为幂次相加的过程,比如:
数值的实际意义
可以看出,十进制由低位到高危分别代表进制数的不同次幂,然后与具体的数字相加,那么最后得出的值,就是十进制代表的数字,比如:

$$
2022 = 2 \times 10^3 + 0 \times 10 ^2 + 2 \times 10 ^ 1 + 2 \times 10 ^ 0
$$

那么我们就可以得出任何进制转化十进制的方法。我们用$B$代表进制数,$N_i$代表每一位,从 0 开始,那么有以下公式:

$$
Number = \sum_i N_i \times B^i
$$

为了在计算机中实现进制转换,还需要一个符号对应表,我们知道十进制有天然的对照表,每个字符就代表真是值,而十六进制需要的数字超过了十进制,所以我们使用$A-F$代表 $10-15$,所以,一下为进制转换程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 字表
let mapping = {
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
6: 6,
7: 7,
8: 8,
9: 9,
A: 10,
B: 11,
C: 12,
D: 13,
E: 14,
F: 15,
};
/**
* 将十六进制数字字符串转换为一个十进制数
* @param HexNumber 十六进制数字字符串
* @returns 转换后的十进制数
*/
function BaseConverting(HexNumber) {
return Array.prototype.reduce.call(
HexNumber,
(pre, current, index, all) => {
return pre + mapping[current] * 16 ** (all.length - index - 1);
},
0
);
return result;
}

console.log(BaseConverting("FE"));

其他进制向十进制转换后同理。

十进制转换为其他进制

十进制转换为其他进制,需要的方法就是不断的去除以底数(进制数,上一小节中的 Base),然后取余数。具体的做法以$36$转换二进制为例:

  • 首先 $38 \div 2 = 19 \cdots 0$ , 这是后确定的是最低位,也就是最低位为$0$。
  • 然后接着$19 \div 2 = 9 \cdots 1$,这个时候的余数$1$已经是经过两轮除以 2 了,所以放在倒数第二位。即:$10$。
  • 然后接着$9 \div 2 = 4 \cdots 1$,得$110$。
  • 接着:$4 \div 2 = 2 \cdots 0$ , 得 0110。
  • $\cdots \cdots$
  • 最后$1 \div 2 = 0 \cdots 1$,得出:$100110$。

即,36 转换为二进制的结果为$100110$。

其他进制也同样如此,同样$39$转换 16 进制:

  • $39 \div 16 = 2 \cdots 7$。
  • $2 \div 16 = 0 \cdots 2$。

得出结果为$27$, 在转换其他进制的时候,我们同样需要使用到字符对照表,我们可以方便的使用一下方法表示以上过程:

$$
36_{(10)} = 100110_{(2)} = 27_{(16)}
$$

小数部分的转换

小数的部分是需要相乘取整的,例如,十进制的$0.8125$转换为 2 进制:

  • $0.8125 \times 2 = 1.625$, 取整数部分,加入到小数点后面:$0.1$
  • 取小数部分继续参与运算:$0.625 \times 2 = 1.25$,取整数加入二进制小数最后:$0.11$
  • 继续运算:$0.25 \times 2 = 0.5$,取整数部分得:$0.110$
  • 继续则得:$0.5 \times 2 = 1$,取整数部分:$0.1101$
  • 小数部分为 0,则运算结束。

当然,有一部分十进制小数在转换为其他进制之后,陷入了死循环,永远不会得出小数部分为零的终止运算条件,那么这部分小数会变成一个其他进制下的循环小数。比如说:$0.3_{(10)}$ 转化为二进制,则会是一个循环小数。

循环小数在参与计算机中的运算时,会有精度上的问题。这也就是困扰前端工程师许久的$0.1+0.2 \ne 0.3$的问题。

小数转换和整数转化的区别与相同点

进制转换中,小数部分和整数部分是分别运算,然后拼接在一起的。他们的区别:

  • 整数运算方法为除以底,取余数,小数运算为乘以底,取整数
  • 整数运算结果需要逆序,小数运算则需要顺序,总而言之,两种方法都需要将每一次的计算姐过从小数点开始往两侧排列。
  • 整数运算肯定能够运算结束,而小数运算则有可能会有循环小数的问题。
  • 二者的相同点是,都需要数表来协助转换。
Author

BorGor

Posted on

2022-01-03

Updated on

2022-01-08

Licensed under

Comments