Code: Select all
;; 0.123456
(defparameter *test-float* (list #x3F #xBF #x9A #xCF #xFA #x7E #xB6 #xBF))
(defun decode-ieee-754 (bytes)
(let ( (sign (if (logbitp 1 (first bytes)) 1 -1))
(exponent (- (logior (ash (logand (first bytes) #x7F) 4)
(ash (second bytes) -4)) 1023))
(significand (+ 4503599627370496
(ash (logand (second bytes) #xF) 48)
(loop for i from 2
with result = 0
do (setf result (+ (ash result 8) (nth i bytes)))
; This looks ugly, I'd rather use "collect" here
when (= i 7) return result))))
(format t "~&sign:~15T~b2,~&exponent:~15T~b2,~&significand:~15T~b2~&" sign exponent significand)
(* sign (/ significand (ash 1 (- 52 exponent))))))
(format t "result: ~F~&" (decode-ieee-754 *test-float*))
Or if you think, that "collect" is not the way to go, please tell, what, in your opinion would be the proper way to do it. If you could explain it, it would be golden!
TIA

EDIT: I've rewritten it like so:
Code: Select all
;; 0.123456
(defparameter *test-float* (list #x3F #xBF #x9A #xCF #xFA #x7E #xB6 #xBF))
(defun decode-ieee-754 (bytes)
(let ( (sign (if (logbitp 1 (first bytes)) 1 -1))
(exponent (- (logior (ash (logand (first bytes) #x7F) 4)
(ash (second bytes) -4)) 1023))
(significand (+ 4503599627370496
(ash (logand (second bytes) #xF) 48)
(reduce #'(lambda (x y) (+ (ash x 8) y))
(subseq bytes 2)))))
(format t "~&sign:~15T~b2,~&exponent:~15T~b2,~&significand:~15T~b2~&" sign exponent significand)
(* sign (/ significand (ash 1 (- 52 exponent))))))
(format t "result: ~F~&" (decode-ieee-754 *test-float*))