笔记5-《程序员的数学》10 进制与 2 进制  

目录
  1. 第一章 0 的故事–计数法
  2. 10 进制计数法
  3. 2 进制计数法
  4. 基数转换
  5. 计算机为什么用 2 进制

第一章 0 的故事–计数法

  • 10 进制计数法

  • 2 进制计数法

  • 基数转换

  • 计算机为什么用 2 进制

10 进制计数法

  • 数字有 0、1、2、3、4、5、6、7、8、9 共 10 种

  • 数位从右往左分别表示个位、十位、百位、千位

  • 小学一年级的回忆:老师让写「十二」,我听成 12 就写下 10 和 2,本子上写的是 102,老师说该写 12 喔

  • 2503 的分解:2 个 1000、5 个 100、0 个 10、3 个 1

    #ruby
    # 2503 = 2 x 10**3 + 5 x 10**2 + 0 x 10**1 + 3 x 10**0
    puts 2 * 10**3 + 5 * 10**2 + 0 * 10**1 + 3 * 10**0 # 2503

    # 1100 = 1 x 2**3 + 1 x 2**2 + 0 x 2**1 + 0 x 2**0
    puts 1 * 2**3 + 1 * 2**2 + 0 * 2**1 + 0 * 2**0 # 12
  • 10 进制计数法的数位全是 10 的幂,这个 10 称作基数(底)

2 进制计数法

  • 数字只有 0、1 共 2 种

  • 数位从右往左分别表示 1 位、2 位、4 位、8 位

  • 数数时到 2 就进位:0、1、10、11、100、101

  • 同样地,1100 是 1 个 8、1 个 4、0 个 2、0 个 1

    10 进制2 进制10 进制2 进制
    0091001
    11101010
    21032100000
    311641000000
    81000991100011

基数转换

  • 10 进制转 2 进制:反复除以 2,看余数是 0 还是 1,再把余数逆向排列

    #ruby
    # 12 转 2 进制:反复除以 2,余数从下往上读
    n = 12
    while n > 0
    puts "#{n} / 2 = #{n / 2} 余数 #{n % 2}"
    n /= 2
    end
    # 12 / 2 = 6 余数 0
    # 6 / 2 = 3 余数 0
    # 3 / 2 = 1 余数 1
    # 1 / 2 = 0 余数 1
  • 余数从下往上读就是 1100,2503 同理得到 100111000111

    #ruby
    def to_bin(n)
    bits = []
    while n > 0
    bits << n % 2
    n /= 2
    end
    bits.reverse.join
    end

    puts to_bin(12) # 1100
    puts to_bin(2503) # 100111000111
    puts 2503.to_s(2) # 100111000111

计算机为什么用 2 进制

  • 计算机表示数只有两种状态:开关切断(0)和开关连通(1)

  • 开关个数可以增加,够多就能表示多大的数

  • 做成能表示 10 种状态的开关理论上也行,结构必定更复杂

  • 1 位加法表的差别最直观

    +01
    001
    1110
  • 10 进制的 1 位加法表是 10 x 10 = 100 格,2 进制只有 2 x 2 = 4 格

  • 缺点是位数变多:2503 在 10 进制是 4 位,在 2 进制是 12 位

  • 10 进制位数少、数字种类多,人类用着顺手,两只手正好 10 个指头

  • 2 进制数字种类少、规则简单,计算机不会算错,也不用靠直觉比大小

  • 所以计算机执行人类的任务时:10 进制 -> 2 进制 -> 计算 -> 10 进制

    #ruby
    # 21 + 19:转 2 进制 -> 用 2 进制算 -> 转回 10 进制
    a = 21.to_s(2)
    b = 19.to_s(2)
    sum = (a.to_i(2) + b.to_i(2)).to_s(2)
    puts "#{a} + #{b} = #{sum} -> #{sum.to_i(2)}"
    # 10101 + 10011 = 101000 -> 40
123.8k