Shammer's Philosophy

My private adversaria

16進数を10進数に戻す関数

逆の処理、10進数を16進数にする、とか、10進数からの変換についてはformatで~xやら~oを使用すればできそうだが、10進数にするのはそうもいかないらしい。formatで~dを使うというのが該当するが、引数が最初から#xで指定されていないといけない。つまり、単純な"2B"という文字列を例にすると

? (format t "~d" "2B")
2B
NIL
?

というように何もしてくれない。もちろん、

? (format t "~d" #x2B)
43
NIL
?

は、動作する。そのため、上の"2B"の場合に43を返すような関数を用意。

? (defun hex2dec (x)
  (let ((result 0) (base 1))
    (if (stringp x)
	(dolist (c (reverse (coerce x 'list)))
	  (cond ((or (equal c #\a) (equal c #\A))
		 (setf result (+ result (* base 10))))
		((or (equal c #\b) (equal c #\B))
		 (setf result (+ result (* base 11))))
		((or (equal c #\c) (equal c #\C))
		 (setf result (+ result (* base 12))))
		((or (equal c #\d) (equal c #\D))
		 (setf result (+ result (* base 13))))
		((or (equal c #\e) (equal c #\E))
		 (setf result (+ result (* base 14))))
		((or (equal c #\f) (equal c #\F))
		 (setf result (+ result (* base 15))))
		(t
		 (setf result (+ result (* base (parse-integer (string c)))))))
	  (setf base (* base 16)))
      (setf result x))
    result))
HEX2DEC
? (hex2dec "2B")
43
?

エラー処理など完全でないところもあるが、とりあえずはこれでよし。