这是一个作业问题,因此请指出正确的方向,不要提供解决方案。 基本上,在Scheme中,我试图构建一个从逻辑门开始的多位加法器。
感谢您的阅读/帮助。
我正在运行的示例是将101001和011101随身携带1个。
我觉得我有一份清单,并且会一直附加吗?但是,如果这是正确的步骤,那么我将无法正常工作。
(define l-and (lambda (x y) (if (and (equal? x 1) (equal? y 1)) 1 0)))
(define l-or (lambda (x y) (if (or (equal? x 1) (equal? y 1)) 1 0)))
(define l-xor (lambda (x y) (if (or (equal? (l-and x y) 1) (and (equal? x 0) (equal? y 0)) ) 0 1)))
(define l-not (lambda (x) (if (equal? x 0) 1 0)))
(define fulladdr (lambda (x y z)
(cons
(l-xor (l-xor x y) z)
(l-or (l-and x y) (l-and z (l-xor x y)))
)
))
(define (removelast lis)
;(display (reverse(cdr (reverse lis)))) For debugging
(if (null? (cdr lis))
'()
(reverse(cdr (reverse lis)
))))
(define (last-element lis)
;(display (car(reverse lis))) For debugging
(if (null? (cdr lis))
'() (car(reverse lis))
))
(define n-bit-addr (lambda (l1 l2 x)
(if (or (null? l1) (null? l2))
'()
(let ((carry (cdr (fulladdr (last-element l1) (last-element l2) x))))
(let (( sum (car (fulladdr (last-element l1) (last-element l2) x))))
;(display carry) For debugging
(cons
(fulladdr (last-element l1) (last-element l2) x)
(n-bit-addr (removelast l1) (removelast l2) carry)
)))))
在此示例以及其他几个示例中运行代码时,我得到正确的输出,例如:((1.1。)(1.0。)(1.0)(0.1)(0.1 )(0。1)) 我试图弄清楚如何格式化它,这样我的输出将是(111000.1)。基本上(二进制。FinalCarry)
答案 0 :(得分:0)
以下是一些观察结果。加法器使用进位,因此您需要对有效数字进行最高有效的运算。
从头到尾创建一个列表。例如。可以创建(1 2)
(cons 1 (cons 2 '()))
,这意味着第二个参数(cons 2 '())
需要完成。
我猜您的参数是(1 0 1 0)
和10
之类的列表中的二进制数字。如果您有一个帮手或一个名为let
的人,到目前为止,您可以拥有两个参数,即进位和求和作为参数,以便可以将它们用作状态。同样,您使用相同的参数调用fulladdr
3次。我认为这是您应该做的:
(define (n-bit-addr l1 l2)
(helper (reverse l1) (reverse l2) 0 '()))
这违反了获取和删除“最后一个”元素以及获取和删除第一个元素的目的,这在Scheme中更容易实现。
剩下的就在这里。我已经摘录了一些挑战。通过不直接使用(n-bit-addr '(1 1) '(1 1 1 0))
和car
可以神奇地解决执行cdr
时发生的情况。
(define (helper l1 l2 carry acc)
;; actual implementation of n-bit-addr
(if (finished? l1 l2)
(finish acc carry)
(let* ((res (fulladdr (car0 l1) (car0 l2) carry))
(sum (car res))
(carry (cdr res)))
(helper (cdr* l1) <??> <??> <??>))))
(define (car0 lst)
;; returns 0 if lst is null? (car lst) otherwise
)
(define (cdr* lst)
;; return '() if lst is null? (cdr lst) otherwise
)
(define (finished? l1 l2)
;; return #t is both are null?
)
(define (finish sum carry)
;; return whatever structure one would want with the last result
;; I would imagine carry could be the the highest bit if it's set. thus
;; (n-bit-addr '(1) '(1)) ; ==> (1 0)
)
现在,如果(1 0 1 0)
不令人满意,您应该制作将number->logic
转换为logic->number
的{{1}}和(1 0 1 0)
。这可以通过列表迭代和算术轻松完成。由于您想知道如何对列表进行编号,因此我将采取另一种方式:
#b1010
请注意,(define (number->logic n)
(let loop ((n n) (acc '()))
(cond ((not (zero? n)) (loop (quotient n 2) (cons (remainder n 2) acc)))
((null? acc) '(0))
(else acc))))
(number->logic #b1010) ; ==> (1 0 1 0)
只是写#b1010
的一种奇特方式
10
另一种方法是将累加器从0开始,并针对列表中的每个元素按顺序将累加器乘以2并加该位。如果列表为(number->logic 10) ; ==> (1 0 1 0)
,则累加器为数字。
null?
我记得在学校用nand门构建加法器,但在编程中却没有这样做。你应该试试看。