数制基础
从小时候起,我们就都使用十进制来表示数量。这种对我们来说似乎很合乎逻辑的命名法,对于古罗马的居民来说可能并非如此。对他们而言,他们用来表示数字的每个符号总是代表相同的值。
I 1
II 2
III 3
IV 4
V 5
所有的
I符号无论放在哪里,都总是代表值 1(一),而
V符号总是代表值 5(五)。然而,在我们的十进制系统中情况并非如此。当我们写下十进制符号 1 时,我们并不总是指值为一(罗马数字中的 I)。例如:
1 I
10 X
100 C
在这些情况下,我们的符号 1 并不总是具有值为一(或罗马数字中的 I)的含义。例如,在第二种情况下,符号 1 代表值为十(或罗马数字中的 X),而在第三种情况下,1 代表值为一百(或 C)。
例如:
275并不等同于 2+7+5,它更应该被分解为 200+70+5。
200
+ 70
5
---
275
因此,第一个“2”符号等同于 200 (2 x 100),第二个“7”符号等同于 70 (7 x 10),而最后一个符号对应于值 5 (5 x 1)。
这是因为我们的系统是位值记数法。因此,一个给定数字的值取决于它在整个被表示的数字中的位置。以上所有内容都可以用一种非常简单的方式进行数学表示。例如,要表示值 182736,我们可以假设每个数字都是它自身乘以 10 的幂,幂次由其位置决定,从右边开始是 10
0,接着是 10
1、10
2,依此类推。
八进制数(基数为 8)
就像我们的“普通”数字是
以 10 为基数(或称十进制)一样,因为我们有 10 个不同的数字(从 0 到 9),
0123456789
八进制数只包括从 0 到 7 的值的表示,
01234567
因此,它的数学基数是 8。在 C++ 中,八进制数总是以一个
0数字开头来表示。让我们看看如何用八进制书写最初的几个数字:
octal decimal
----- -------
0 0 (zero)
01 1 (one)
02 2 (two)
03 3 (three)
04 4 (four)
05 5 (five)
06 6 (six)
07 7 (seven)
010 8 (eight)
011 9 (nine)
012 10 (ten)
013 11 (eleven)
014 12 (twelve)
015 13 (thirteen)
016 14 (fourteen)
017 15 (fifteen)
020 16 (sixteen)
021 17 (seventeen)
因此,例如,数字 17(十七,或罗马数字中的 XVII)表示为
021在 C++ 中作为一个八进制数。我们可以将我们之前看到的十进制数的机制应用到八进制数上,只需考虑其基数是 8。例如,取八进制数
071263:
因此,八进制数
071263用十进制数表示为 29363。
十六进制数(基数为 16)
就像十进制数有 10 个不同的数字来表示(0123456789),八进制数有 8 个(01234567),十六进制数有 16 个不同的数字,它们由数字 0 到 9 和字母 A、B、C、D、E、F 表示,这些共同构成了我们表示以 16 为基数的数字所需的 16 个不同符号。
hexadecimal decimal
----------- -------
0 0 (zero)
0x1 1 (one)
0x2 2 (two)
0x3 3 (three)
0x4 4 (four)
0x5 5 (five)
0x6 6 (six)
0x7 7 (seven)
0x8 8 (eight)
0x9 9 (nine)
0xA 10 (ten)
0xB 11 (eleven)
0xC 12 (twelve)
0xD 13 (thirteen)
0xE 14 (fourteen)
0xF 15 (fifteen)
0x10 16 (sixteen)
0x11 17 (seventeen)
在 C++ 中,十六进制数的前缀是
0x(零,x)。
我们再次可以使用相同的方法将一个数字从一个基数转换到另一个基数。
二进制表示
在比特的世界里,八进制和十六进制数相对于我们的十进制数有一个相当大的优势,那就是它们的基数(8 和 16)是 2 的完美倍数(分别为 2
3 和 2
4),这使得我们可以比从十进制数(其基数为 2x5)更容易地将这些基数转换为二进制。例如,假设我们想将以下二进制序列转换为其他基数的数字:
110011111010010100
为了将其转换为十进制,我们需要进行类似于我们之前用来从十六进制或八进制转换的数学运算,这将得到十进制数 212628。
然而,要将这个序列转换为八进制,我们只需要几秒钟,即使是数学最差的人也能一眼看出来:由于 8 是 2
3,我们将二进制值分成 3 个数字一组:
110 011 111 010 010 100
现在我们只需将每组分别转换为八进制数基数:
110 011 111 010 010 100
6 3 7 2 2 4
得到的结果是数字 637224。这个过程同样可以反向进行,从八进制转换到二进制。
为了用十六进制数进行运算,我们只需执行相同的过程,但是将二进制值分成 4 个数字一组,因为 16 = 2
4:
11 0011 1110 1001 0100
3 3 E 9 4
因此,二进制表达式 110011111010010100 在 C++ 中可以表示为 212628(十进制)、0637224(八进制)或 0x33e94(十六进制)。
十六进制代码在计算机科学中特别有意义,因为当今的计算机基于由 8 个二进制位组成的字节,因此每个字节正好对应 2 个十六进制数可以表示的范围。因此,它非常频繁地用于表示与二进制基数相互转换的值。