计算机的起源是数学中的二进制计数法

计算机起源

计算机的起源是数学中的二进制计数法

什么是二进制计数法?

日常的十进制

阿拉伯数字由从 0 到 9 这样 10 个计数符号组成,并采取进位制法,每10进一位,2871为例

图 7

其中 ^ 表示幂或次方运算。十进制的数位(千位、百位、十位等)全部都是 10^n 的形式。需要特别注意的是,任何非 0 数字的 0 次方均为 1。在这个新的表示式里,10 被称为十进制计数法的基数.

二进制

我们将基数改为2,就可以理解二进制的展示了.例如110101.

二进制的数位就是 2^n 的形式

图 8

其他进制

我们只要基于基数的改动,就可以使用任一进制来展示我们的数字.

进制转换

1
2
3
4
5
6
7
8
9
10
11
io.open()

var str = tostring(123,16) //转换为十六进制字符串
var num = tonumber(str,16) //将十六进制字符串转换为数值

io.print(
"二进制",tostring( 123,2) ,
"八进制",tostring( 123,8) ,
"十六进制",tostring( 123,16) ,
"十进制",tostring( 123 )
);

将数值转换为字符串的tostring()函数,以及将字符串转换为数值的tonumber()函数,都可选使用第二个参数指定应用于转换的进制(2到36之间).

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

组成计算机系统的逻辑电路通常只有两个状态,即开关的接通与断开。

二进制的位操作

向左移位

二进制 110101 向左移一位,就是在末尾添加一位 0,因此 110101 就变成了 1101010

图 9

如果将 1101010 换算为十进制,就是 106,你有没有发现,106 正好是 53 的 2 倍 > 二进制左移一位,其实就是将数字翻倍。

数字溢出

所谓数字溢出,就是二进制数的位数超过了系统所指定的位数。目前主流的系统都支持至少 32 位的整型数字

向右移位

二进制 110101 向右移一位,就是去除末尾的那一位,因此 110101 就变成了 11010

ps. 我们将 11010 换算为十进制,就是 26,正好是 53 除以 2 的整数商

二进制右移一位,就是将数字除以 2 并求整数商的操作

图 10

代码示例

1
2
console.log(5 << 2);  //返回值20
console.log(1000 >>> 8); //返回值3

左移位是 <<,那右移位为什么是 >>> 而不是 >> 呢 ?

  • >> 也是右移操作
  • 二进制数值中最高一位是符号位

图 13

如果数字是 -53 呢?那么第 32 位就不是 0

负数:

图 14

逻辑右移 >>

会改变符号位

图 15

算术右移 >>

图 16

位的“或”

二进制的“1”和“0”分别对应逻辑中的“真”和“假”,可以针对位进行逻辑操作

逻辑“或”的意思是,参与操作的位中只要有一个位是 1,那么最终结果就是 1,也就是“真”。如果我们将二进制 110101 和 100011 的每一位对齐,进行按位的“或”操作,就会得到 110111。

图 17

位的“与”

同理,我们也可以针对位进行逻辑“与”的操作。“与”的意思是,参与操作的位中必须全都是 1,那么最终结果才是 1(真),否则就为 0(假)。如果我们将二进制 110101 和 100011 的每一位对齐,进行按位的“与”操作,就会得到 100001。

图 18

位的“异或”

逻辑“异或”和“或”有所不同,它具有排异性,也就是说如果参与操作的位相同,那么最终结果就为 0(假),否则为 1(真)。所以,如果要得到 1,参与操作的两个位必须不同,这就是此处“异”的含义。我们将二进制 110101 和 100011 的每一位对齐,进行按位的“异或”操作,可以得到结果是 10110。

图 19

按位与、按位或、按位异或 操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a=1;
var b=0;

//按位与&:两个操作数都是1,结果才是1
console.log( a&b ) //结果是0

//按位或:两个操作数只要有一个是1,结果就是1
console.log( a|b ) //结果是1

//按位异或:两个数字一样,结果为0;两个数字不一样,结果就是1。
console.log( a^b ) //结果是1

//简单的方法:数字求负,在减1
console.log( ~a ) //结果是-2