一个计算器完成计算需要哪些部件?
运算单元 控制单元 存储(寄存器)输入 输出
今天我们主要关注前面两者
准备工作
我们要有存数据的寄存器
寄存器可以通过列表实现
先看一下我们的寄存器
(
(func getEmptyList () (
list 0 0 0 0 0 0 0 0
))
(define r-a (mark-list 8))
(define r-b (mark-list 8))
(define r-c (mark-list 8))
(define r-d (mark-list 8))
(define r-e (mark-list 8))
(define r-temp (mark-list 8))
(define r-opt (getEmptyList))
(define r-zero (getEmptyList))
(func copy (l r) (
(define len (length l))
(define r-len (length r))
(for ((i 0) (< i len) (i (+ i 1))) (
(list-set! r (- r-len i 1) (list-ref l (- len i 1)))
))
))
;左移
(func sl(l num) (
(define len (length l))
(for((i num)(< i len)(i (+ i 1)))(
(list-set! l (- i num) (list-ref l i))
))
; 后几位 是 0
(for ((i (- len num)) (< i len) (i (+ i 1))) (
list-set! l i 0
))
))
)
计算单元
加法
(
define add ((lambda () (
(func not-eq (a b ) (
and
(xand a b)
(or a b)
))
(func not-eq-and (a b) (
(define j (and a b))
(define p (not-eq a b))
(cons j p)
))
(func all-add (a b j) (
(define r1 (not-eq-and a b))
(define r2 (not-eq-and (cdr r1) j))
(cons (or (car r1) (car r2)) (cdr r2))
))
(lambda (l-a l-b l-r) (
(define j 0)
(define cons0 nil)
(copy r-zero l-r)
(
for ((i (- (length l-a) 1)) (< -1 i) (i (- i 1))) (
(set! cons0 (all-add (list-ref l-a i) (list-ref l-b i) j))
(set! j (car cons0))
(list-set! l-r i (cdr cons0))
)
)
))
))))
)
乘法
(
(func multi (l-a l-b l-r) (
; todo 支持负数运算
(define j nil)
(define len (length l-b))
(define l-0 (mark-list 8))
(define l-1 (mark-list 8))
(copy r-zero l-r)
(for ((i (- len 1)) (< -1 i) (i (- i 1))) (
(set! j (- len i 1))
(if (less? zero (list-ref l-b i)) (
(copy l-a l-0)
(sl l-0 j)
(add l-0 l-r l-1)
(copy l-1 l-r)
))
))
l-r
))
)
负数
(
;负数单元
(define toNegative(lambda (list l-r) (
(add (map (lambda (o) (not o)) list) (map (lambda (o i) (eqv? i (- (length list) 1))) list) l-r)
)))
)
控制单元
一些布尔逻辑的扩展
(
(func eq? (a b) (
or (and a b) (xor a b)
))
(func eql? (l-a l-b) (
(define r 1)
(for((i 0)(< i (length l-a))(i (+ i 1))) (
(set! r (and r (eq? (list-ref l-a i) (list-ref l-b i))))
))
r
))
(func less? (a b) (
and (xor a zero) (or b zero)
))
(define-macro if (lambda(p exp) (
`(and ,p ,exp)
)))
)
接受数字和指令
(
;5位长就够了 0开头的是数字 1 开头的是指令 + - * /
(func inputNumber (l-a l-r) (
; r = (r*10)+a
(define ten (list 0 0 0 0 1 0 1 0))
(multi l-r ten r-e)
(add r-e l-a r-temp)
(copy r-temp l-r)
))
(func clac (l-a l-r) (
; 0 + 1 - 2 * 3 /
(if (eql? l-r (list 0 0 0 1 0 0 0 0)) (
(add r-a r-b r-temp)
(copy r-temp r-a)
))
(if (eql? l-r (list 0 0 0 1 0 0 0 1)) (
(toNegative r-a r-e)
(copy r-e r-a)
(add r-a r-b r-temp)
(copy r-temp r-a)
))
(if (eql? l-r (list 0 0 0 1 0 0 1 0)) (
(multi r-a r-b r-temp)
(copy r-temp r-a)
))
(copy l-a l-r)
(copy r-a r-b)
(copy r-zero r-a)
))
)
输入
(
(func input (l) (
(define car0 (car l))
(if (eq? zero car0) (
(define l0 (getEmptyList))
(copy l l0)
(inputNumber l0 r-a)
))
(if (less? zero car0) (
(clac l r-opt)
))
))
)
输出
(
(func println (x) (
(display x)
(newline)
))
(func show () (
(if (eql? r-a r-zero) (
println r-b
))
(if (not (eql? r-a r-zero)) (
println r-a
))
))
)
测试
(
; 二进制 1 执行后 r-a => 0001
(input (list 0 0 0 0 1))
; 二进制 1 执行后 r-a => 1011
(input (list 0 0 0 0 1))
; 二进制 执行后 r-opt => 10001 代表 减法 , r-a => 0000 r-b => 1011
(input (list 1 0 0 0 1))
; 二进制 11 执行后 r-a => 0011
(input (list 0 0 0 1 1))
; 二进制 执行后 r-opt => 10000 代表 加法 ,r-a => 11101 r-b => 01011 r-a => 00000 r-b => 01000
(input (list 1 0 0 0 0))
(show)
)
=> (#f #f #f #f 1 #f #f #f)
附上全部代码
(
(func println (x) (
(display x)
(newline)
))
(func ten2two (t) (
(define l (mark-list 8))
(copy r-zero l)
(define i (length l))
(while (< 0 t)(
(set! i (- i 1))
(list-set! l i (% t 2))
(set! t (/ t 2))
))
l
))
(func getEmptyList () (
list 0 0 0 0 0 0 0 0
))
; 寄存器 不去实现 用 list 代替 r0-r8 move a b
(define zero 0)
(define r-a (mark-list 8))
(define r-b (mark-list 8))
(define r-c (mark-list 8))
(define r-d (mark-list 8))
(define r-e (mark-list 8))
(define r-temp (mark-list 8))
(define r-opt (getEmptyList))
(define r-zero (list 0 0 0 0 0 0 0 0))
(func copy (l r) (
(define len (length l))
(define r-len (length r))
(for ((i 0) (< i len) (i (+ i 1))) (
(list-set! r (- r-len i 1) (list-ref l (- len i 1)))
))
))
;左移
(func sl(l num) (
(define len (length l))
(for((i num)(< i len)(i (+ i 1)))(
(list-set! l (- i num) (list-ref l i))
))
; 后几位 是 0
(for ((i (- len num)) (< i len) (i (+ i 1))) (
list-set! l i 0
))
))
;只用 and or not 作为基础
;(func and (a b) (and a b))
;(func or (a b) (or a b))
;(func not (a) (not a))
(func xor (a b) (not (or a b)))
(func xand (a b) (not (and a b)))
;--先实现计算单元
(define add ((lambda () (
(func not-eq (a b ) (
and
(xand a b)
(or a b)
))
(func not-eq-and (a b) (
(define j (and a b))
(define p (not-eq a b))
(cons j p)
))
(func all-add (a b j) (
(define r1 (not-eq-and a b))
(define r2 (not-eq-and (cdr r1) j))
(cons (or (car r1) (car r2)) (cdr r2))
))
(lambda (l-a l-b l-r) (
(define j 0)
(define cons0 nil)
(copy r-zero l-r)
(
for ((i (- (length l-a) 1)) (< -1 i) (i (- i 1))) (
(set! cons0 (all-add (list-ref l-a i) (list-ref l-b i) j))
(set! j (car cons0))
(list-set! l-r i (cdr cons0))
)
)
))
))))
(func multi (l-a l-b l-r) (
; todo 支持负数运算
(define j nil)
(define len (length l-b))
(define l-0 (mark-list 8))
(define l-1 (mark-list 8))
(copy r-zero l-r)
(for ((i (- len 1)) (< -1 i) (i (- i 1))) (
(set! j (- len i 1))
(if (less? zero (list-ref l-b i)) (
(copy l-a l-0)
(sl l-0 j)
(add l-0 l-r l-1)
(copy l-1 l-r)
))
))
l-r
))
;负数单元
(define toNegative(lambda (list l-r) (
(add (map (lambda (o) (not o)) list) (map (lambda (o i) (eqv? i (- (length list) 1))) list) l-r)
)))
;--实现控制单元
(func eq? (a b) (
or (and a b) (xor a b)
))
(func eql? (l-a l-b) (
(define r 1)
(for((i 0)(< i (length l-a))(i (+ i 1))) (
(set! r (and r (eq? (list-ref l-a i) (list-ref l-b i))))
))
r
))
(func less? (a b) (
and (xor a zero) (or b zero)
))
(define-macro if (lambda(p exp) (
`(and ,p ,exp)
)))
;5位长就够了 0开头的是数字 1 开头的是指令 + - * /
(func inputNumber (l-a l-r) (
; r = (r*10)+a
(define ten (list 0 0 0 0 1 0 1 0))
(multi l-r ten r-e)
(add r-e l-a r-temp)
(copy r-temp l-r)
))
(func clac (l-a l-r) (
; 0 + 1 - 2 * 3 /
(if (eql? l-r (list 0 0 0 1 0 0 0 0)) (
(add r-a r-b r-temp)
(copy r-temp r-a)
))
(if (eql? l-r (list 0 0 0 1 0 0 0 1)) (
(toNegative r-a r-e)
(copy r-e r-a)
(add r-a r-b r-temp)
(copy r-temp r-a)
))
(if (eql? l-r (list 0 0 0 1 0 0 1 0)) (
(multi r-a r-b r-temp)
(copy r-temp r-a)
))
(copy l-a l-r)
(copy r-a r-b)
(copy r-zero r-a)
))
(func input (l) (
(define car0 (car l))
(if (eq? zero car0) (
(define l0 (getEmptyList))
(copy l l0)
(inputNumber l0 r-a)
))
(if (less? zero car0) (
(clac l r-opt)
))
))
(func show () (
(if (eql? r-a r-zero) (
println r-b
))
(if (not (eql? r-a r-zero)) (
println r-a
))
))
;测试 add
(copy (list 0 0 0 0 1 0 1 0 ) r-a)
(copy (list #f #f #f #f #f #f #f 1 ) r-b)
;(println r-a)
(add r-a r-b r-c)
; ( r-a r-b r-c)
;(println r-c)
; 测试左移
(define a0 (list 0 0 0 0 0 0 0 1 ) )
(sl a0 3)
; (println a0)
;(println (ten2two 10))
;测试 multi
(copy r-zero r-c)
;(multi r-b r-a r-c)
;(println r-c)
(copy r-zero r-a)
(input (list 0 0 0 0 1))
(input (list 0 0 0 0 1))
(input (list 1 0 0 0 1))
(input (list 0 0 0 1 1))
(input (list 1 0 0 0 0))
(show)
)
总结
计算的本质是机械性的操作,而如何把这种机械的操作通过机器来实现出来的就是我们现在看到布尔代数映射到逻辑门的电子计算机,也就是说电子计算机是对机械性操作的的实现之一,有空我会从头开始去讲一下数字到底是什么?进位的好处是什么?数字又是如何计算的? 还有计算是如何通过逻辑与函数抽象出来的?
抽象的函数又是如何转换为机械性操作的?计算机可否有其他种实现方式?
而 这些最基础的知识只需要初中所学的内容即可,或者我们可以只需要小学一年级的数学知识