2012-05-04 37 views
3

假設我有一個整數,例如二進制中的109,1101101。如何迭代這個數字的位,例如:[64,32,8,4,1]?在lisp中做這件事的好方法是什麼?我應該通過添加一個案例來修改for宏嗎?還是應該將整數轉換爲位向量或列表?lisp循環遍歷整數位的方式

回答

6

如果你只想處理「ones」,那麼循環遍歷所有比特的效率並不高。這是我想在這種情況下

(defmacro do-bits ((var x) &rest body) 
    "Evaluates [body] forms after binding [var] to each set bit in [x]" 
    (let ((k (gensym))) 
    `(do ((,k ,x (logand ,k (1- ,k)))) 
     ((= ,k 0)) 
     (let ((,var (logand ,k (- ,k)))) 
     ,@body)))) 

它使用的是位安定漂亮的2補事實,數字和其對面的回報至少顯著設置位和位安定了許多,一個少做比數字零這個最不重要的設置位。

注意,該處理從最低顯著設置位工作最顯著(在你的例子中,你使用相反的順序)

0

這可能是不太成熟,但會做。請注意,在使用它之前你需要測試`zerop',因爲如果你用0調用它,迭代回調將不會被調用。

(defun iterate-bits-of (x handler) 
    (unless (zerop x) 
    (and (funcall handler (logand x 1)) 
    (iterate-bits-of (ash x -1) handler)))) 

(iterate-bits-of 
#b1101101 
#'(lambda (x) (not (format t "bit ~b~&" x)))) 
;; bit 1 
;; bit 0 
;; bit 1 
;; bit 1 
;; bit 0 
;; bit 1 
;; bit 1 

另請注意,大數'灰」可能會變得相當昂貴,在這種情況下,你可能需要使用6502的變種。

5

看看logbitp,它可以讓你訪問一個整數的個別位。例如,

(loop for i below (integer-length 109) 
     collect (if (logbitp i 109) 1 0)) 

=> (1 0 1 1 0 1 1)