本文包含十进制正整数转换二进制数、十进制负整数转换二进制数、以及十进制小数转换成二进制数的方法讲解,想了解为什么0.1无法用二进制很好地表示的朋友可以直接看文章末尾。
首先我们来了解一下如何将十进制正整数转换成二进制。
- 将十进制数除以2取余数,直到商为0停止计算;
- 对余数逆序排列,所得即为该十进制数的二进制表示形式。
如十进制数11:
11 / 2 = 5 ... 1
5 / 2 = 2 ... 1
2 / 2 = 1 ... 0
1 / 2 = 0 ... 1 (这里 1 / 2 的商为0,所以不再进行运算)
将余数逆序排列,得到1011,对其进行验证:1 x 20 + 1 x 21 + 0 x 22 + 1 x 23 = 11,结果正确。
用8位表示法,在高位补0,结果为00001011。
接着来说说十进制负整数怎么转换成二进制数。
- 和上面的第一步相似,对这个负整数的绝对值除以2取余数,直到商为0;
- 对余数进行逆序排列得到原码,再对得出的二进制数进行取反得到反码,最后在末尾加1得到补码,补码即为转换结果。
举个栗子,十进制负整数 -13取其绝对值后运算:
13 / 2 = 6 ... 1
6 / 2 = 3 ... 0
3 / 2 = 1 ... 1
1 / 2 = 0 ... 1
将逆序所得的二进制数用8位表示法表示:00001101(原码),对原码的每一位进行取反,得到11110010(反码),反码加1得到11110011(补码)。
顺便提一句,已知有符号的二进制数可通过观察其最高位的值来判断是正整数还是负整数,最高位是0就是正,1为负。
在知道符号的情况下,二进制负正数转换成十进制正整数只需减1并取反得到原码,再将原码转换成十进制数即可。
然后是十进制小数转换二进制数。
- 让十进制小数位乘2,取每次运算所得积的整数部位,直到积的小数部位为0停止计算。
- 将第一步所得结果正序排列,并在前面补上0和小数点即可。
再举个栗子,十进制小数0.125:
0.125 x 2 = 0.250 —— 取整数 0
0.25 x 2 = 0.50 —— 取整数 0
0.5 x 2 = 1.0 —— 取整数 1
正序排列后补上0和小数点:0.001,这个就是结果啦。
验证一下:0 x 20 + 0 x 2-1 + 0 x 2-2 + 1 x 2-3 = 0.125,没毛病。
最后来探讨一下为什么0.1没法用二进制很好地表示。
我们用刚才讲到的十进制小数转换成二进制的方法来试着转换一下0.1:
0.1 x 2 = 0.2 —— 取整数 0
0.2 x 2 = 0.4 —— 取整数 0
0.4 x 2 = 0.8 —— 取整数 0
0.8 x 2 = 1.6 —— 取整数 1
0.6 x 2 = 1.2 —— 取整数 1
0.2 x 2 = 0.4 —— 取整数 0
. . .
得到一个无限循环小数,所以。。。你是在为难我胖虎。
这也就能解释为什么 float 类型的 0.1f 与 double 类型的 (1.0/10) 不相等,因为这两种数据类型精度不同,对这个无限循环小数取的位数不同,自然也就不相等了。