Skip to content

Latest commit

 

History

History
207 lines (126 loc) · 6.86 KB

foundations_of_computer_science.md

File metadata and controls

207 lines (126 loc) · 6.86 KB

《计算机科学导论》笔记

最近在读《计算机科学导论》,想要对于编程了解更多,就免不了去了解计算机的底层知识。记录下阅读所感或总结,暂时不懂的也没关系,过段时间再读一遍或许有不一样的收获。

第二章 数字系统

十进制转换为二进制

该操作分为两个步骤,对整数部分与小数部分分开进行转换。先给出两个步骤的流程图。

整数部分: 十进制转x进制整数

小数部分: 十进制转x进制小数

以十进制数 6.25 为例转换为二进制数。

首先处理整数部分:

  • 6 / 2 得 3 余 0
  • 3 / 2 得 1 余 1
  • 1 / 2 得 0 余 1

所以得到转换后的二进制整数部分为 110

接下来处理小数部分:

  • 0.25 * 2 得 0.5 取整数部分 0
  • 0.5 * 2 得 1 取整数部分 1

所以得到转换后的二进制小数部分为 01

最终结果为 110.01,那么尝试着用代码来实现一下这个过程。

function decimalToBinary(num, target/* 目标进制 */) {
  // 分离整数和小数
  let [int, deci] = String(num).split('.');
  const result = [];

  // 先处理整数
  int = parseInt(int, 10);
  if (int === 0) result.push(0);
  while (int !== 0) {
    result.unshift(int % target);
    int = parseInt(int / target, 10);
  }
  
  // 处理小数
  if (deci) {
    deci = parseFloat(`0.${deci}`);
    result.push('.');

    while (!Number.isInteger(deci)) {
      deci *= target;
      result.push(parseInt(deci, 10));
    }
  }

  return result.join('');
}

console.log(decimalToBinary(6.25, 2));

二进制转十进制

相比起十进制转换为二进制,二进制转十进制更简单一些。

流程图如下: x进制转十进制

以二进制数 1010.101 为例进行转换。(**表示幂运算)

  • 整数部分为:2**0 * 0 + 2**1 * 1 + 2**2 * 0 + 2**3 * 1 = 10
  • 小数部分为:2**-1 * 1 + 2**-2 * 0 + 2**-3 * 1 = 0.625

最终结果为 10.625,以下为代码实现。

function binaryToDecimal(num) {
  let [int, deci] = String(num).split('.');
  int = int.split('').reverse().reduce((ret, item, index) => ret + item * 2 ** index, 0);
  if (!deci) return int;
  deci = deci.split('').reduce((ret, item, index) => ret + item * 2 ** (-index - 1), 0);
  return int + deci;
}

console.log(binaryToDecimal(1010.101));

八进制、十六进制转换为十进制,与二进制转换为十进制类似,唯一的不同就是底数。


第三章 数据存储

如何存储数字

  1. 无符号表示法
  2. 符号加绝对值表示法
  3. 二进制补码表示法

目前几乎所有的计算机都采用二进制补码表示法来存储数字。

要了解二进制补码表示法需要先了解反码和补码的运算。

  1. 反码:简单反转各个位,将0变为1,1变为0。例:10010 => 01101

  2. 补码:补码有两种计算方法。例 10010 => 01110

    • 先进行一次反码计算,然后加1
    • 从最右侧开始复制位,直到有1被复制,接着对其余的位取反码

二进制补码表示法在存储数字的时候,有效范围为0 ~ 2**n -1,并且该范围会被划分为两个相等的子范围,左半边存储正整数,右半边存储负整数。最后,这两半会按照左负右正的习惯进行位置交换。书中图例如下:

二进制补码表示法

然后来看二进制补码表示法具体是如何存储整数的。

  • 存储

    1. 将整数转换为二进制数
    2. 如果整数是正的或者是零,直接存储。如果是负数,对其进行补码操作,然后存储
  • 取出

    1. 如果最左位是1(负数),计算机对其进行补码操作,如果最左位是0(正数),不进行任何操作
    2. 将二进制数转换为十进制数(加上正负号)

扩展知识

探寻 JavaScript 精度问题以及解决方案


第四章 数据运算

二进制运算在平时使用js的时候很少有机会使用,所以之前也没有仔细看过。现在仅记录运算的规则,等到有机会进行实践的时候再来重新温习这一章。

逻辑运算

  1. 非(NOT),一元运算符。对输入进行反转。0变为1,1变为0。
  2. 与(AND),二元运算符。接受2个输入,如果都是1,则输出1,否则输出0。
  3. 或(OR),二元运算符。接受2个输入,如果都是0,则输出0,否则输出1。
  4. 异或(XOR),二元运算符。接受2个输入,如果输入相同则输入0,否则输出1。

移位运算

  1. 右移,把每一位向右移动一个位置,最右位丢失,最左位填0。
  2. 左移,与右移操作相反。

第五章 计算机组成

计算机的组成主要分为三大类。

中央处理单元(CPU)

用于数据的运算。主要包含三个组成部分:算术逻辑单元、控制单元、寄存器组。

主存储器

存储单元的集合,每个存储单元都有唯一标识,就是所谓的“地址”。

存储器分为RAMROM

由于计算机需要很多存储器,但由于高速存储器价格高昂,所以会采用存储器分层。对于速度要求较高时会采用高速存储器,中速存储器用来存储经常访问的数据,而低速存储器则存储访问频率较低的数据。

存储器层次

输出/输入子系统

主要包含键盘、鼠标、外接硬盘等设备,使计算机具备与外界通信的能力。


第六章 计算机网络和因特网

协议分层的必要性不言而喻,每一层使用更低层的服务,同时向更高层提供服务。如果需要替换某一层的服务,则只需对该层进行修改或替换,而不影响高层和低层。

应用层

作为TCP/IP协议簇中的最高层,该层不向其他协议提供服务,仅仅是接收传输层对其提供的协议进行消费。常见的有FTPTelnetSMTPHTTPRIPNFSDNS等。

传输层

传输层的第一个义务是提供进程间的服务,有多种办法来完成进程间的通信,最常用的是通过端口(PORT),端口号是0 ~ (2**16 - 1)之间的整数表示的。该层常见的协议主要是UDPTCP

网络层

主要负责源到目的地的消息发送。

数据链路层

该层是网络中连接起来以后能够构成因特网的区域。能够通过有线或无线的形式来完成。

物理层

将数据链路层接收的位转换成用于传输的电磁信号。

互联网协议扩展知识

互联网协议入门(一)

互联网协议入门(二)