02-二进制:不了解计算机的源头,你学什么编程 - 图1

我们都知道,计算机的起源是数学中的二进制计数法。可以说,没有二进制,就没有如今的计算机系统。那什么是二进制呢?为什么计算机要使用二进制,而不是我们日常生活中的十进制呢?如何在代码中操作二进制呢?专栏开始,我们就从计算机认知的起源——二进制出发,讲讲它在计算机中的“玄机”。

1. 什么是二进制计数法?

为了让你更好地理解二进制计数法,我们先来简单地回顾一下人类计数的发展史。

原始时代,人类用路边的小石子,来统计放牧归来的羊只数量,这表明我们很早就产生了计数的意识。后来,罗马人用手指作为计数的工具,并在羊皮上画出Ⅰ、Ⅱ、Ⅲ来代替手指的数量。表示一只手时,就写成“Ⅴ”形,表示两只手时,就画成“ⅤⅤ”形等等。

公元 3 世纪左右,印度数学家(也有说法是阿拉伯人)发明了阿拉伯数字。阿拉伯数字由从 0 到 9 这样 10 个计数符号组成,并采取进位制法,高位在左,低位在右,从左往右书写。由于阿拉伯数字本身笔画简单,演算便利,因此它们逐渐在各国流行起来,成为世界通用的数字。

日常生活中,我们广泛使用的十进制计数法,也是基于阿拉伯数字的。这也是十进制计数法的基础。因此,相对其他计数方法,十进制最容易被我们所理解。

让我们来观察一个数字:2871。

02-二进制:不了解计算机的源头,你学什么编程 - 图2

其中 ^ 表示幂或次方运算。十进制的数位(千位、百位、十位等)全部都是 10^n 的形式。需要特别注意的是,任何非 0 数字的 0 次方均为 1。在这个新的表示式里,10 被称为十进制计数法的基数,也是十进制中“十”的由来。这个我想你应该好理解,因为这和我们日常生活的习惯是统一的。

明白了十进制,我们再试着用类似的思路来理解二进制的定义。我以二进制数字 110101 为例,解释给你听。我们先来看,这里 110101 究竟代表了十进制中的数字几呢?

刚才我们说了,十进制计数是使用 10 作为基数,那么二进制就是使用 2 作为基数,类比过来,二进制的数位就是 2^n 的形式。如果需要将这个数字转化为人们易于理解的十进制,我们就可以这样来计算:

02-二进制:不了解计算机的源头,你学什么编程 - 图3

按照这个思路,我们还可以推导出八进制(以 8 为基数)、十六进制(以 16 为基数)等等计数法,很简单,我在这里就不赘述了。

至此,你应该已经理解了什么是二进制。但是仅有数学的理论知识是不够的,结合相关的代码实践,相信你会有更深刻的印象。

基于此,我们来看看二进制和十进制数在 Java 语言中是如何互相转换的,并验证一下我们之前的推算。我这里使用的是 Java 语言来实现的,其他主流的编程语言实现方式都是类似的。

这段代码的实现采用了 Java 的 BigInteger 类及其 API 函数,我都加了代码注释,并且穿插一些解释,你应该可以看懂。

首先,我们引入 BigInteger 包,通过它和 Integer 类的 API 函数进行二进制和十进制的互相转换。

  1. import java.math.BigInteger;
  2. public class Lesson1_1 {
  3. /**
  4. * @Description: 十进制转换成二进制
  5. * @param decimalSource
  6. * @return String
  7. */
  8. public static String decimalToBinary(int decimalSource) {
  9. BigInteger bi = new BigInteger(String.valueOf(decimalSource)); //转换成BigInteger类型,默认是十进制
  10. return bi.toString(2); //参数2指定的是转化成二进制
  11. }
  12. /**
  13. * @Description: 二进制转换成十进制
  14. * @param binarySource
  15. * @return int
  16. */
  17. public static int binaryToDecimal(String binarySource) {
  18. BigInteger bi = new BigInteger(binarySource, 2); //转换为BigInteger类型,参数2指定的是二进制
  19. return Integer.parseInt(bi.toString()); //默认转换成十进制
  20. }
  21. }

然后,我们通过一个十进制数和一个二进制数,来验证一下上述代码的正确性。

  1. public static void main(String[] args) {
  2. int a = 53;
  3. String b = "110101";
  4. System.out.println(String.format("数字%d的二进制是%s", a, Lesson1_1.decimalToBinary(a))); //获取十进制数53的二进制数
  5. System.out.println(String.format("数字%s的十进制是%d", b, Lesson1_1.binaryToDecimal(b))); //获取二进制数110101的十进制数
  6. }

这段代码运行的结果是:十进制数字 53 的二进制是 110101,二进制数字 110101 的十进制是 53。

好了,关于十进制和二进制的概念以及进制之间的相互转换,你应该都很清楚了。既然有十进制,又有二进制,你可能就要问了,为啥计算机使用的是二进制而不是十进制呢?

2. 计算机为什么使用二进制?

我觉得,计算机使用二进制和现代计算机系统的硬件实现有关。组成计算机系统的逻辑电路通常只有两个状态,即开关的接通与断开。