如何在普通的 lisp 中使用 (zerop #*000)?
How to (zerop #*000) in common lisp?
有没有一种有效的方法来检查位向量是否全为零? (我在 Linux 上使用 SBCL。)我查看了文档但找不到合适的函数。到目前为止我想到的最好的是:
(defun bit-zerop (array)
(equal array (make-array (length array) :element-type 'bit)))
(bit-zerop #*000)
我也试过了
(defun bit-zerop (array)
(dotimes (i (length array))
(if (eql (sbit array i) 1)
(return-from bit-zerop nil)))
t)
但是在更大的位向量上它比第一个版本慢了大约 100 倍。 (这是预期的,因为每个 64 位字被读取 64 次,我猜,而不是一次)。当然,第一个版本是次优的,它必须分配一个新数组。
编辑: 提到的解决方案的时间安排。
编辑 2: 类型声明的时间。
(defun bit-zerop-1 (array)
;; (declare (simple-bit-vector array))
(equal array (make-array (length array) :element-type 'bit)))
(defun bit-zerop-2 (array)
;; (declare (simple-bit-vector array))
(every #'zerop array))
(defun bit-zerop-3 (array)
;; (declare (simple-bit-vector array))
(loop
for bit across array
never (= bit 1)))
(defun bit-zerop-4 (array)
;; (declare (simple-bit-vector array))
(not (find 1 array)))
(dolist (func '(bit-zerop-1 bit-zerop-2 bit-zerop-3 bit-zerop-4))
(dolist (size '(10 100 1000))
(let ((x (make-array size :element-type 'bit)))
(format t "Testing ~a on ~a elements~%" func size)
(time
(dotimes (i 1000000)
(funcall func x))))))
给予
===============================================
方法 尺寸 10 尺寸 100 尺寸 1000
------------------ 未类型化 ------------------
bit-zerop-1 0.030 秒 0.030 秒 0.058 秒
bit-zerop-2 0.112 秒 1.000 秒 9.324 秒
bit-zerop-3 0.111 秒 0.935 秒 8.742 秒
bit-zerop-4 0.047 秒 0.047 秒 0.063 秒
------------------ 打字--------------------
bit-zerop-1 0.025 秒 0.023 秒 0.040 秒
bit-zerop-2 0.036 秒 0.315 秒 3.005 秒
bit-zerop-3 0.041 秒 0.348 秒 3.346 秒
bit-zerop-4 0.010 秒 0.012 秒 0.026 秒
===============================================
我不确定是否有任何特殊的位逻辑功能,请参见例如here.
但是这个怎么样?
(loop
for bit across #*0000
never (= bit 1))
这里有一个选项:
(defun bit-vector-zerop (bit-vector)
(not (find 1 bit-vector)))
这在 SBCL 上没有缺点并且非常有效。如果您可以将参数声明为位向量,速度会更快。
有没有一种有效的方法来检查位向量是否全为零? (我在 Linux 上使用 SBCL。)我查看了文档但找不到合适的函数。到目前为止我想到的最好的是:
(defun bit-zerop (array)
(equal array (make-array (length array) :element-type 'bit)))
(bit-zerop #*000)
我也试过了
(defun bit-zerop (array)
(dotimes (i (length array))
(if (eql (sbit array i) 1)
(return-from bit-zerop nil)))
t)
但是在更大的位向量上它比第一个版本慢了大约 100 倍。 (这是预期的,因为每个 64 位字被读取 64 次,我猜,而不是一次)。当然,第一个版本是次优的,它必须分配一个新数组。
编辑: 提到的解决方案的时间安排。
编辑 2: 类型声明的时间。
(defun bit-zerop-1 (array)
;; (declare (simple-bit-vector array))
(equal array (make-array (length array) :element-type 'bit)))
(defun bit-zerop-2 (array)
;; (declare (simple-bit-vector array))
(every #'zerop array))
(defun bit-zerop-3 (array)
;; (declare (simple-bit-vector array))
(loop
for bit across array
never (= bit 1)))
(defun bit-zerop-4 (array)
;; (declare (simple-bit-vector array))
(not (find 1 array)))
(dolist (func '(bit-zerop-1 bit-zerop-2 bit-zerop-3 bit-zerop-4))
(dolist (size '(10 100 1000))
(let ((x (make-array size :element-type 'bit)))
(format t "Testing ~a on ~a elements~%" func size)
(time
(dotimes (i 1000000)
(funcall func x))))))
给予
=============================================== 方法 尺寸 10 尺寸 100 尺寸 1000 ------------------ 未类型化 ------------------ bit-zerop-1 0.030 秒 0.030 秒 0.058 秒 bit-zerop-2 0.112 秒 1.000 秒 9.324 秒 bit-zerop-3 0.111 秒 0.935 秒 8.742 秒 bit-zerop-4 0.047 秒 0.047 秒 0.063 秒 ------------------ 打字-------------------- bit-zerop-1 0.025 秒 0.023 秒 0.040 秒 bit-zerop-2 0.036 秒 0.315 秒 3.005 秒 bit-zerop-3 0.041 秒 0.348 秒 3.346 秒 bit-zerop-4 0.010 秒 0.012 秒 0.026 秒 ===============================================
我不确定是否有任何特殊的位逻辑功能,请参见例如here.
但是这个怎么样?
(loop
for bit across #*0000
never (= bit 1))
这里有一个选项:
(defun bit-vector-zerop (bit-vector)
(not (find 1 bit-vector)))
这在 SBCL 上没有缺点并且非常有效。如果您可以将参数声明为位向量,速度会更快。