Potentially Surprising Behavior
Without specifying the number of bits we are interested in the inversions don't necessarily behave the way a programmer might expect:
(invert-bits (invert-bits 8)) ; => 0
; because
(invert-bits 8) ; => 7
(invert-bits 7) ; => 0
In general two successive calls to invert-bits
does not obey the principle of least surprise:
(invert-bits (invert-bits 54)) ; => 6
(invert-bits (invert-bits 1024)) ; => 0
(invert-bits (invert-bits 4000)) ; => 32
The issue, if it is actually an issue, arises from inverting bits in the abstract rather than in a particular context. In a practical application, there is probably a specific type that we are concerned with, for example a 16-bit integer.
Analysis of Issue
As written the function throws away information by treating a leading bit value of 0 as equivalent to the absence of information. From an information theory standpoint, a zero leading bit is information.
Sketch of information retaining function
Using Common Lisp's &Optional
parameters is a mechanism for passing the number of interesting bits through the recursive calls to invert-bits
. Using values
at the bottom of the function passes the bit-depth across the recursive calls.
(defun invert-bits (n &Optional number-of-bits)
;; code which will:
;; turn n into some-number taking into account
;; the bits if provided
(values some-number
(if number-of-bits
number-of-bits
(integer-length n))))