Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the last n bits of a given octet (byte) to zero?

I got a octet (byte) and a number of relevant-bits and I want to keep the first n (relevant-bits) of that given byte and set the remaining bits to zero.

E.g.

The number 217 where the first 4 bits are relevant would convert to 208

0                    0
0 1 2 3 4 5 6 7      0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+  ==> +-+-+-+-+-+-+-+
1 1 0 1 1 0 0 1      1 1 0 1 0 0 0 0

The number 255 where the first 8 (or greater) bits are relevant would not change at all

0                    0
0 1 2 3 4 5 6 7      0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+  ==> +-+-+-+-+-+-+-+
1 1 1 1 1 1 1 1      1 1 1 1 1 1 1 1

I wrote this function to solve the problem

(defun list-of-bits (integer)
  (let ((bits '()))
    (dotimes (position (integer-length integer) bits)
      (push (ldb (byte 1 position) integer) bits))))

(defun calculate-octet (byte rel-bits)
  (if (< rel-bits 8)
      (parse-integer 
       (FORMAT nil "~{~a~}"
           (replace (list-of-bits byte)
            '(0 0 0 0 0 0 0 0) 
            :start1 rel-bits
            :end1 8
            :start2 0
            :end2 rel-bits))
       :radix 2)
      byte))

But this solution seems bad for two reasons

  1. it splits the integer into a list before processing it

  2. it prints the list into a string which is again parsed

I know that common-lisp provides functions to directly access the bits and bytes (ldb,logbitp) but I could not figure out a way to use them for my problem.

Is there a way to solve the problem more efficient (or at least more elegant)?

like image 225
Sim Avatar asked Dec 05 '25 13:12

Sim


2 Answers

CL-USER 6 > (mask-field (byte 4 4) 217)
208

Note also that it does not mask the field of the original number, but returns a new number with the bit field masked.

like image 154
Rainer Joswig Avatar answered Dec 07 '25 15:12

Rainer Joswig


There are already three answers, so I may as well add another two:

No one suggested DPB yet. Always nice with a nod to the PDP-10.

(defun calculate-octet (byte bits)
  (dpb 0 (byte bits bits) byte))

Again with the LOGAND.

(defun calculate-octet (byte bits)
  (logand byte (ash -1 (- 8 bits))))
like image 34
Lars Brinkhoff Avatar answered Dec 07 '25 16:12

Lars Brinkhoff



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!