簡體   English   中英

倒置了一下

[英]Inversion of a bit

我一直無法找到簡單地反轉一下的common-lisp函數(或宏)。 有些函數可以對位數組進行操作,邏輯函數可以對數字進行操作,但這些函數似乎需要額外的步驟來反轉單個位變量。 一個暫時的解決方案是

(define-modify-macro invertf (&rest args)
  (lambda (bit)
    (if (= bit 0) 1 0)))

哪個有效,但我想知道是否有更優雅或更簡單的解決方案。

按位運算有很多運算符:

例如,您可以使用

(logxor bit 1)

這會給你0如果該位是1, 1 ,如果該位為0:

(logxor 0 1) ; => 1
(logxor 1 1) ; => 0

當然你可以將bit部分作為第二個參數:

(logxor 1 bit)

獎金

也許您可以創建一個函數並使用類型聲明對其進行優化:

(defun invert (bit)
  "Inverts a bit"
  (declare (type bit bit))
  (logxor bit 1))

運行后(disassemble 'invert)我在SBCL上得到了以下結果:

沒有類型聲明:

; disassembly for INVERT
; Size: 56 bytes. Origin: #x10059E97FC
; 7FC:       498B4C2460       MOV RCX, [R12+96]               ; thread.binding-stack-pointer
                                                              ; no-arg-parsing entry point
; 801:       48894DF8         MOV [RBP-8], RCX
; 805:       BF02000000       MOV EDI, 2
; 80A:       488BD3           MOV RDX, RBX
; 80D:       4883EC18         SUB RSP, 24
; 811:       48896C2408       MOV [RSP+8], RBP
; 816:       488D6C2408       LEA RBP, [RSP+8]
; 81B:       B904000000       MOV ECX, 4
; 820:       FF1425980B1020   CALL QWORD PTR [#x20100B98]     ; TWO-ARG-XOR
; 827:       488B5DF0         MOV RBX, [RBP-16]
; 82B:       488BE5           MOV RSP, RBP
; 82E:       F8               CLC
; 82F:       5D               POP RBP
; 830:       C3               RET
; 831:       0F0B10           BREAK 16                        ; Invalid argument count trap

WITH類型聲明

; disassembly for INVERT
; Size: 25 bytes. Origin: #x1005767CA9
; A9:       498B4C2460       MOV RCX, [R12+96]                ; thread.binding-stack-pointer
                                                          ; no-arg-parsing entry point
; AE:       48894DF8         MOV [RBP-8], RCX
; B2:       488BD3           MOV RDX, RBX
; B5:       4883F202         XOR RDX, 2
; B9:       488BE5           MOV RSP, RBP
; BC:       F8               CLC
; BD:       5D               POP RBP
; BE:       C3               RET
; BF:       0F0B10           BREAK 16                         ; Invalid argument count trap

在我看來,類型聲明保存了一些操作。

讓我們衡量差異:

(defun invert (bit)
  "Inverts a bit"
  (declare (type bit bit))
  (logxor bit 1))

(defun invert-no-dec (bit)
  "Inverts a bit"
  (logxor bit 1))

現在運行:

(time (loop repeat 1000000 do (invert 1)))

輸出:

Evaluation took:
  0.007 seconds of real time
  0.005164 seconds of total run time (0.005073 user, 0.000091 system)
  71.43% CPU
  14,060,029 processor cycles
  0 bytes consed

在跑步的時候:

(time (loop repeat 1000000 do (invert-no-dec 1)))

輸出:

Evaluation took:
  0.011 seconds of real time
  0.011327 seconds of total run time (0.011279 user, 0.000048 system)
  100.00% CPU
  25,505,355 processor cycles
  0 bytes consed

似乎類型聲明使函數的速度提高了一倍。 必須注意的是,對invert的調用可能會抵消性能增益,除非你使用(declaim (inline invert)) 來自CLHS

inline指定編譯器需要對由function-names命名的函數進行內聯調用; 也就是說,指定函數名的代碼應該集成到調用例程中,顯示​​“在行中”代替過程調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM