陈进佳 发表于 2024-7-5 14:10:10

浮点数与16进制字符串互转


在部分二进制文件中,浮点数是需要转换换为16进制字符串来存储的。
由于在LISP中没有单精度浮点数和双精度浮点数转16进制字符串函数,前些天为此伤透脑筋,有偿悬赏也未有人帮忙解决。
在查阅算法以及论坛资料后,算是完美解决了这个难题。

其中引用了大神baitang36大神的的内部函数itoa,以及高飞鸟大神的激活内部函数的代码,在此拜谢!
程序源代码如下,由于不会使用上传代码工具,敬请谅解


;;=============================================================
;;; 程序加载后,就可以用tranf来激活一个系统隐藏的函数         
;;; 用法:(tranf "内部函数名")                                 
;;; 参数:函数名的字符串                                       
;;; 返回:T存在或者是可用的内部函数,nil不存在或则无效         
;;; 作者:highflybird                                          
;;; 例子:(tranf "get-logical-drives")                        
;;; 此程序得到网友baitang36和不死猫的大力帮助,特此致谢!      
;;; 另外借鉴了tryhi和其他网友的代码,在此一并感谢!            
;;;-------------------------------------------------------------
(defun HFB-LOAD-TRANF (/ f o l s b)
(setq o (strcat (getenv "UserProfile") "\\Intern.fas"))
(if (findfile o)
    (vl-file-delete o)
)
(setq        l '(70       65   83   52        45   70          73   76   69       13   49   13
          49       32   36   1        36   51          51   32   48       32   36   86
          58       76   80   80        0    105110116101       1141100
          108       11211245        115121109102117       11045   62
          97       1080           0        57   3          0    22   36
           )
)
(setq b (vlax-make-safearray 17 (cons 0 (1- (length l)))))
(vlax-safearray-fill b l)
(setq s (vlax-create-object "ADODB.Stream"))
(vlax-put s 'type 1)
(vlax-invoke s 'open)
(vlax-invoke-method s 'Write b)
(vlax-invoke s 'saveToFile o 2)
(vlax-invoke s 'close)
(vlax-release-object s)
(mapcar
    'set
    '(:lpp intern lpp-symfun->al)
    (mapcar 'eval (load o))
)
(vl-file-delete o)
(defun tranf (s) (lpp-symfun->al (intern s :lpp)))
(tranf 'al-add-subr-name)
(mapcar
    'al-add-subr-name
    '(al-add-subr-name lpp-symfun->al intern tranf)
)
(if lpp-symfun->al
    (princ "\n已打开内部函数转普通函数大门.\n")
    (princ "\n激活内部函数转普通函数失败!\n")
)
)
;激活保留函数功能的自定义函数
(or lpp-symfun->al (HFB-LOAD-TRANF))

;激活itoa进制转换函数(itoa [进制 int])最多32进制
(tranf "itoa")

;字符串分段函数
;参数 str 类型sting
;参数 dimod 当dimod为int时,按int分割(string-Split "asfsgsb" 2)-> '( "as" "fs" gs" b")
;参数 dimod 当dimod为string时,按string 分割(string-Split "assfssgssb" "ss" )-> '( "a" "f" g" b")
(defun string-Split (str dimod / str dimod n nlst)
(if (= (TYPE dimod) 'INT)
    (progn
      (setq n       1
          nlst nil
      )
      (while (<= n (strlen STR))
        (setq nlst (cons (substr str n dimod) nlst))
        (setq n (+ n dimod))
      )
      (reverse nlst)
    )
    (progn
      (while (setq n (vl-string-search dimod str))
        (setq nlst (cons (substr str 1 n) nlst)
              str(substr str (+ 1 (strlen dimod) n))
        )
      )
      (reverse (cons str nlst))
    )
)
)

;二进制字符串转整数
;(2str-to-int "1101")->13
(defun 2str-to-int(str / n int)
(setq n (strlen str) int 0)
(while (/= str "")
    (setq n (- n 1))
    (if (= "1" (substr str 1 1))
      (setq int (+ int (expt 2 n)))
      )
    (setq str (substr str 2))
    )
int
)
;32float2hex单精度浮点数转16进制字符串
;real 单精度浮点数(此处用小数表示)
;(32float2hex 117.1468)->"42EA4B29"
(defun 32float2hex (real / 16str 2str N laststr 2strlst 2strtointlst
                  16strlst)
(if (equal real 0 0.00000000000001)
    (setq 16str "00000000")
    (progn
                                        ;判断符号位
      (if (> real 0)
        (setq 2str "0")
        (setq 2str "1")
      )
      (setq real (abs real))
      (SETQ N 127)
      (WHILE (< 2 REAL)
        (SETQ REAL (/ REAL 2.0))
        (SETQ N (1+ N))
      )
      (setq 2str (strcat 2str (itoa n 2))) ;增加阶码位
      (setq real (1- real))                ;取尾数部分
      (setq laststr "")                        ;尾数部分二进制初始值
      (repeat 23;尾数位数
        (setq real (* 2.0 real))
        (if (>= real 1)
          (progn (setq laststr (strcat laststr "1"))
               (setq real (1- real))
          )
          (setq laststr (strcat laststr "0"))
        )
      )
      (setq 2str (strcat 2str laststr))        ;完整的32位二进制
      (setq 2strlst (string-Split 2str 4)) ;每四位分割成表
      (setq 2strtointlst (mapcar '2str-to-int 2strlst))
                                        ;每四位转换成十进制整数
      (setq 16strlst (mapcar '(lambda (X) (itoa x 16)) 2strtointlst))
                                        ;每个整数转换为16进制字符串
      (setq 16str (strcase(apply 'strcat 16strlst))) ;表中字符串按顺序合并
    )
)
)
;64float2hex双精度浮点数转16进制字符串
;real 双精度浮点数(此处用小数表示)
;(64float2hex 117.1468)->"405D49652BD3C361"
(defun 64float2hex (real / 16str 2str N laststr 2strlst 2strtointlst
                  16strlst)
(if (equal real 0 0.00000000000001)
    (setq 16str "0000000000000000")
    (progn
                                        ;判断符号位
      (if (> real 0)
        (setq 2str "0")
        (setq 2str "1")
      )
      (setq real (abs real))
      (SETQ N 1023)
      (WHILE (< 2 REAL)
        (SETQ REAL (/ REAL 2.0))
        (SETQ N (1+ N))
      )
      (setq 2str (strcat 2str (itoa n 2))) ;增加阶码位
      (setq real (1- real))                ;取尾数部分
      (setq laststr "")                        ;位数部分二进制初始值
      (repeat 52
        (setq real (* 2.0 real))
        (if (>= real 1)
          (progn (setq laststr (strcat laststr "1"))
               (setq real (1- real))
          )
          (setq laststr (strcat laststr "0"))
        )
      )
      (setq 2str (strcat 2str laststr))        ;完整的64位二进制
      (setq 2strlst (string-Split 2str 4)) ;每四位分割成表
      (setq 2strtointlst (mapcar '2str-to-int 2strlst))
                                        ;每四位转换成十进制整数
      (setq 16strlst (mapcar '(lambda (X) (itoa x 16)) 2strtointlst))
                                        ;每个整数转换为16进制字符串
      (setq 16str (strcase(apply 'strcat 16strlst))) ;表中字符串按顺序合并
    )
)
)

;长度为1的字符串16进制转10进制
(DEFUN 16TO10(str)
(setq str(strcase str))
(ascii "9")
(if(> (ascii str) 57)
    (- (ascii str) 55)
    (read str)
    )
)
;单字节字符串转10进制
(DEFUN byteto10(str)
(setq str(strcase str))
(if (< (strlen str) 2)(setq str (strcat "0" str)))
(+ (* 16 (16TO10 (substr str 1 1))) (16TO10 (substr str 2 1)))
)
;多字节字符串转10进制
(DEFUN bytesto10(str)
(setq lst (mapcar 'byteto10 (string-Split str 2)))
)
;单字符串前面补位0,n补位个数
(DEFUN add0str (str n)
(setq str (strcase str))
(while (< (strlen str) n)
    (setq str (strcat "0" str ))
)
str
)
;单字符串后面补位0,n补位个数
(DEFUN addstr0 (str n)
(setq str (strcase str))
(while (< (strlen str) n)
    (setq str (strcatstr "0"))
)
str
)
;两个常规字符代表一个字节,不足前面补0
(defun onebytes(str)
(if (/= (strlen str) 2)(add0str str 2)str)
)
;64hex2float 64位16进制字符串转双精度浮点数
;str 长度位16的字符串
;(64hex2float "405D49652BD3C361")->"117.1468"
(defun 64hex2float (str / 2lst 2str fhw zsw wsw zsm ws wswlst)
(setq lst (mapcar '16TO10 (string-Split str 1)))
(setq 2lst (mapcar '(lambda (X) (add0str (itoa x 2) 4)) lst))
(setq 2str (apply 'strcat 2lst))
(setq fhw (substr 2str 1 1))
(setq zsw (substr 2str 2 11))
(setq wsw (substr 2str 13 52))
(setq zsm (- (2str-to-int zsw) 1023))
(setq ws 0.000000000000001)
(setq wswlst (reverse (string-split wsw 1)))
(while wswlst
    (if        (= "1" (car wswlst))
      (setq ws (/ (1+ ws) 2.0))
      (setq ws (/ ws 2.0))
    )
    (if        (> ws 1)
      (setq ws (- ws 1))
    )
    (setq wswlst (cdr wswlst))
)
(if (= "1" fhw)
    (- 0 (* (+ 1 ws) (expt 2 zsm)))
    (* (+ 1 ws) (expt 2 zsm))
)
)
;32hex2float 32位16进制字符串转双精度浮点数
;str 长度位8的字符串
;(32hex2float "42EA4B29")->"117.1468"
(defun 32hex2float (str / 2lst 2str fhw zsw wsw zsm ws wswlst)
(setq lst (mapcar '16TO10 (string-Split str 1)))
(setq 2lst (mapcar '(lambda (X) (add0str (itoa x 2) 4)) lst))
(setq 2str (apply 'strcat 2lst))
(setq fhw (substr 2str 1 1))
(setq zsw (substr 2str 2 8))
(setq wsw (substr 2str 10 23))
(setq zsm (- (2str-to-int zsw) 127))
(setq ws 0.0000001)
(setq wswlst (reverse (string-split wsw 1)))
(while wswlst
    (if        (= "1" (car wswlst))
      (setq ws (/ (1+ ws) 2.0))
      (setq ws (/ ws 2.0))
    )
    (if        (> ws 1)
      (setq ws (- ws 1))
    )
    (setq wswlst (cdr wswlst))
)
(if (= "1" fhw)
    (- 0 (* (+ 1 ws) (expt 2 zsm)))
    (* (+ 1 ws) (expt 2 zsm))
)
)




MZ_li 发表于 2024-7-5 17:09:13

;;=============================================================
;;; 程序加载后,就可以用tranf来激活一个系统隐藏的函数         
;;; 用法:(tranf "内部函数名")                                 
;;; 参数:函数名的字符串                                       
;;; 返回:T存在或者是可用的内部函数,nil不存在或则无效         
;;; 作者:highflybird                                          
;;; 例子:(tranf "get-logical-drives")                        
;;; 此程序得到网友baitang36和不死猫的大力帮助,特此致谢!      
;;; 另外借鉴了tryhi和其他网友的代码,在此一并感谢!            
;;;-------------------------------------------------------------
(defun HFB-LOAD-TRANF (/ f o l s b)
(setq o (strcat (getenv "UserProfile") "\\Intern.fas"))
(if (findfile o)
    (vl-file-delete o)
)
(setq      l '(70         65   83   52      45   70          73   76   69         13   49   13
            49         32   36   1      36   51          51   32   48         32   36   86
            58         76   80   80      0    105110116101         1141100
            108         11211245      115121109102117         11045   62
            97         1080         0      57   3          0    22   36
         )
)
(setq b (vlax-make-safearray 17 (cons 0 (1- (length l)))))
(vlax-safearray-fill b l)
(setq s (vlax-create-object "ADODB.Stream"))
(vlax-put s 'type 1)
(vlax-invoke s 'open)
(vlax-invoke-method s 'Write b)
(vlax-invoke s 'saveToFile o 2)
(vlax-invoke s 'close)
(vlax-release-object s)
(mapcar
    'set
    '(:lpp intern lpp-symfun->al)
    (mapcar 'eval (load o))
)
(vl-file-delete o)
(defun tranf (s) (lpp-symfun->al (intern s :lpp)))
(tranf 'al-add-subr-name)
(mapcar
    'al-add-subr-name
    '(al-add-subr-name lpp-symfun->al intern tranf)
)
(if lpp-symfun->al
    (princ "\n已打开内部函数转普通函数大门.\n")
    (princ "\n激活内部函数转普通函数失败!\n")
)
)
;激活保留函数功能的自定义函数
(or lpp-symfun->al (HFB-LOAD-TRANF))

;激活itoa进制转换函数(itoa [进制 int])最多32进制
(tranf "itoa")

;字符串分段函数
;参数 str 类型sting
;参数 dimod 当dimod为int时,按int分割(string-Split "asfsgsb" 2)-> '( "as" "fs" gs" b")
;参数 dimod 当dimod为string时,按string 分割(string-Split "assfssgssb" "ss" )-> '( "a" "f" g" b")
(defun string-Split (str dimod / str dimod n nlst)
(if (= (TYPE dimod) 'INT)
    (progn
      (setq n         1
            nlst nil
      )
      (while (<= n (strlen STR))
      (setq nlst (cons (substr str n dimod) nlst))
      (setq n (+ n dimod))
      )
      (reverse nlst)
    )
    (progn
      (while (setq n (vl-string-search dimod str))
      (setq nlst (cons (substr str 1 n) nlst)
            str(substr str (+ 1 (strlen dimod) n))
      )
      )
      (reverse (cons str nlst))
    )
)
)

;二进制字符串转整数
;(2str-to-int "1101")->13
(defun 2str-to-int(str / n int)
(setq n (strlen str) int 0)
(while (/= str "")
    (setq n (- n 1))
    (if (= "1" (substr str 1 1))
      (setq int (+ int (expt 2 n)))
      )
    (setq str (substr str 2))
    )
int
)
;32float2hex单精度浮点数转16进制字符串
;real 单精度浮点数(此处用小数表示)
;(32float2hex 117.1468)->"42EA4B29"
(defun 32float2hex (real / 16str 2str N laststr 2strlst 2strtointlst
                  16strlst)
(if (equal real 0 0.00000000000001)
    (setq 16str "00000000")
    (progn
                                        ;判断符号位
      (if (> real 0)
      (setq 2str "0")
      (setq 2str "1")
      )
      (setq real (abs real))
      (SETQ N 127)
      (WHILE (< 2 REAL)
      (SETQ REAL (/ REAL 2.0))
      (SETQ N (1+ N))
      )
      (setq 2str (strcat 2str (itoa n 2))) ;增加阶码位
      (setq real (1- real))                ;取尾数部分
      (setq laststr "")                        ;尾数部分二进制初始值
      (repeat 23;尾数位数
      (setq real (* 2.0 real))
      (if (>= real 1)
          (progn (setq laststr (strcat laststr "1"))
               (setq real (1- real))
          )
          (setq laststr (strcat laststr "0"))
      )
      )
      (setq 2str (strcat 2str laststr))      ;完整的32位二进制
      (setq 2strlst (string-Split 2str 4)) ;每四位分割成表
      (setq 2strtointlst (mapcar '2str-to-int 2strlst))
                                        ;每四位转换成十进制整数
      (setq 16strlst (mapcar '(lambda (X) (itoa x 16)) 2strtointlst))
                                        ;每个整数转换为16进制字符串
      (setq 16str (strcase(apply 'strcat 16strlst))) ;表中字符串按顺序合并
    )
)
)
;64float2hex双精度浮点数转16进制字符串
;real 双精度浮点数(此处用小数表示)
;(64float2hex 117.1468)->"405D49652BD3C361"
(defun 64float2hex (real / 16str 2str N laststr 2strlst 2strtointlst
                  16strlst)
(if (equal real 0 0.00000000000001)
    (setq 16str "0000000000000000")
    (progn
                                        ;判断符号位
      (if (> real 0)
      (setq 2str "0")
      (setq 2str "1")
      )
      (setq real (abs real))
      (SETQ N 1023)
      (WHILE (< 2 REAL)
      (SETQ REAL (/ REAL 2.0))
      (SETQ N (1+ N))
      )
      (setq 2str (strcat 2str (itoa n 2))) ;增加阶码位
      (setq real (1- real))                ;取尾数部分
      (setq laststr "")                        ;位数部分二进制初始值
      (repeat 52
      (setq real (* 2.0 real))
      (if (>= real 1)
          (progn (setq laststr (strcat laststr "1"))
               (setq real (1- real))
          )
          (setq laststr (strcat laststr "0"))
      )
      )
      (setq 2str (strcat 2str laststr))      ;完整的64位二进制
      (setq 2strlst (string-Split 2str 4)) ;每四位分割成表
      (setq 2strtointlst (mapcar '2str-to-int 2strlst))
                                        ;每四位转换成十进制整数
      (setq 16strlst (mapcar '(lambda (X) (itoa x 16)) 2strtointlst))
                                        ;每个整数转换为16进制字符串
      (setq 16str (strcase(apply 'strcat 16strlst))) ;表中字符串按顺序合并
    )
)
)

;长度为1的字符串16进制转10进制
(DEFUN 16TO10(str)
(setq str(strcase str))
(ascii "9")
(if(> (ascii str) 57)
    (- (ascii str) 55)
    (read str)
    )
)
;单字节字符串转10进制
(DEFUN byteto10(str)
(setq str(strcase str))
(if (< (strlen str) 2)(setq str (strcat "0" str)))
(+ (* 16 (16TO10 (substr str 1 1))) (16TO10 (substr str 2 1)))
)
;多字节字符串转10进制
(DEFUN bytesto10(str)
(setq lst (mapcar 'byteto10 (string-Split str 2)))
)
;单字符串前面补位0,n补位个数
(DEFUN add0str (str n)
(setq str (strcase str))
(while (< (strlen str) n)
    (setq str (strcat "0" str ))
)
str
)
;单字符串后面补位0,n补位个数
(DEFUN addstr0 (str n)
(setq str (strcase str))
(while (< (strlen str) n)
    (setq str (strcatstr "0"))
)
str
)
;两个常规字符代表一个字节,不足前面补0
(defun onebytes(str)
(if (/= (strlen str) 2)(add0str str 2)str)
)
;64hex2float 64位16进制字符串转双精度浮点数
;str 长度位16的字符串
;(64hex2float "405D49652BD3C361")->"117.1468"
(defun 64hex2float (str / 2lst 2str fhw zsw wsw zsm ws wswlst)
(setq lst (mapcar '16TO10 (string-Split str 1)))
(setq 2lst (mapcar '(lambda (X) (add0str (itoa x 2) 4)) lst))
(setq 2str (apply 'strcat 2lst))
(setq fhw (substr 2str 1 1))
(setq zsw (substr 2str 2 11))
(setq wsw (substr 2str 13 52))
(setq zsm (- (2str-to-int zsw) 1023))
(setq ws 0.000000000000001)
(setq wswlst (reverse (string-split wsw 1)))
(while wswlst
    (if      (= "1" (car wswlst))
      (setq ws (/ (1+ ws) 2.0))
      (setq ws (/ ws 2.0))
    )
    (if      (> ws 1)
      (setq ws (- ws 1))
    )
    (setq wswlst (cdr wswlst))
)
(if (= "1" fhw)
    (- 0 (* (+ 1 ws) (expt 2 zsm)))
    (* (+ 1 ws) (expt 2 zsm))
)
)
;32hex2float 32位16进制字符串转双精度浮点数
;str 长度位8的字符串
;(32hex2float "42EA4B29")->"117.1468"
(defun 32hex2float (str / 2lst 2str fhw zsw wsw zsm ws wswlst)
(setq lst (mapcar '16TO10 (string-Split str 1)))
(setq 2lst (mapcar '(lambda (X) (add0str (itoa x 2) 4)) lst))
(setq 2str (apply 'strcat 2lst))
(setq fhw (substr 2str 1 1))
(setq zsw (substr 2str 2 8))
(setq wsw (substr 2str 10 23))
(setq zsm (- (2str-to-int zsw) 127))
(setq ws 0.0000001)
(setq wswlst (reverse (string-split wsw 1)))
(while wswlst
    (if      (= "1" (car wswlst))
      (setq ws (/ (1+ ws) 2.0))
      (setq ws (/ ws 2.0))
    )
    (if      (> ws 1)
      (setq ws (- ws 1))
    )
    (setq wswlst (cdr wswlst))
)
(if (= "1" fhw)
    (- 0 (* (+ 1 ws) (expt 2 zsm)))
    (* (+ 1 ws) (expt 2 zsm))
)
)

tryhi 发表于 2024-7-9 18:19:19

这么好的函数居然没评论
页: [1]
查看完整版本: 浮点数与16进制字符串互转