我试图在LISP中编写一个代码来乘以两个64位数字。 在ubuntu平台上使用SBCL编译程序。 我的算法如下。
1)将第一个数字转换为64位二进制表示。
2)对第二个数字进行二次加法,第二个次数为自己。
我编写了以下函数将十进制数转换为二进制数(将十进制数和空列表作为参数)
(defun bin (N B)
(cond
((= N 0) B)
((evenp N)(bin (round (/ N 2)) (cons 0 B)))
((oddp N) (bin (floor (/ N 2)) (cons 1 B)))
))
执行二进制加法后的函数。(取nos位,初始进位,第一个二进制no,第二个二进制no,空列表)
(defun addbin (n carry L1 L2 L3)
(cond
((< n 0) (cons carry L3))
((and (= (lastE L1 n) 0) (= (lastE L2 n) 0) (= carry 0)) (addbin (- n 1) 0 L1 L2 (cons 0 L3)))
((and (= (lastE L1 n) 0) (= (lastE L2 n) 0) (= carry 1)) (addbin (- n 1) 0 L1 L2 (cons 1 L3)))
((and (= (lastE L1 n) 0) (= (lastE L2 n) 1) (= carry 0)) (addbin (- n 1) 0 L1 L2 (cons 1 L3)))
((and (= (lastE L1 n) 0) (= (lastE L2 n) 1) (= carry 1)) (addbin (- n 1) 1 L1 L2 (cons 0 L3)))
((and (= (lastE L1 n) 1) (= (lastE L2 n) 0) (= carry 0)) (addbin (- n 1) 0 L1 L2 (cons 1 L3)))
((and (= (lastE L1 n) 1) (= (lastE L2 n) 0) (= carry 1)) (addbin (- n 1) 1 L1 L2 (cons 0 L3)))
((and (= (lastE L1 n) 1) (= (lastE L2 n) 1) (= carry 0)) (addbin (- n 1) 1 L1 L2 (cons 0 L3)))
((and (= (lastE L1 n) 1) (= (lastE L2 n) 1) (= carry 1)) (addbin (- n 1) 1 L1 L2 (cons 1 L3)))
))
以二进制数返回第n位的补充函数是(take list&amp; n)
(defun lastE (L n)
(cond
((= n 0) (first L))
(t (lastE (rest L) (- n 1)))
))
和乘法函数为
(defun bin_mult(nA A B)
(cond
((= B 1) A)
(t (bin_mult (addbin (- (length A) 1) 0 A nA ()) A (- B 1)))
))
我正在执行以下代码来执行乘法
(print "Enter two numbers to be multiplied")
(finish-output nil)
(defvar num1)
(defvar num2)
(defvar a)
(setq num1 (read))
(setq num2 (read))
(setq a (bin num1 ()))
(defvar cnt)
(setq cnt (integer-length num1))
(print cnt)
(dotimes (i (- 63 cnt))
(push 0 a)
)
(print "First number in binary format is" )
(print a)
(print "Multiplication two numbers with concurrency is")
(print (bin_mult a a num2))
我得到以下输出(10 * 4)
(1 0 1 0)
我尝试在命令提示符下跟踪bin_mult函数的执行。 我得到以下输出(trace bin_mult x x 4),其中x是(1 0 1 0)
(bin_mult x x 4)
0: (BIN_MULT (1 0 1 0) (1 0 1 0) 4)
1: (BIN_MULT (1 0 1 0 0) (1 0 1 0) 3)
2: (BIN_MULT (1 0 1 0 0) (1 0 1 0) 2)
3: (BIN_MULT (1 0 1 0 0) (1 0 1 0) 1)
3: BIN_MULT returned (1 0 1 0)
2: BIN_MULT returned (1 0 1 0)
1: BIN_MULT returned (1 0 1 0)
0: BIN_MULT returned (1 0 1 0)
(1 0 1 0)
某种程度上不会添加中间结果。 请帮助解决这段代码中的错误..
谢谢..
答案 0 :(得分:1)
我不确定你要做什么,但你可以稍后进行乘法并模拟溢出。
(defun multiply-overflow (bits &rest xs)
(let ((result (reduce #'* xs :initial-value 1)))
(multiple-value-bind (_ remainder) (floor result (1- (ash 1 bits)))
remainder)))
(multiply-overflow 64 1000000000000 1000000000000)
; ==> 2003764205206950850