lisp - 如何在普通 lisp 中将 double-float 转换为字节数组,反之亦然?

标签 lisp common-lisp

对于整数(32 位或 4 字节)我可以这样做;

(defun get-u4 (arr pos)
  (let ((u4 0))
    (setf (ldb (byte 8 0) u4) (aref arr pos))
    (setf (ldb (byte 8 8) u4) (aref arr (+ pos 1)))
    (setf (ldb (byte 8 16) u4) (aref arr (+ pos 2)))
    (setf (ldb (byte 8 24) u4) (aref arr (+ pos 3)))
  u4))

(defun put-u4 (arr pos int)
  (setf (aref arr pos) (ldb (byte 8 0) int))
  (setf (aref arr (+ pos 1)) (ldb (byte 8 8) int))
  (setf (aref arr (+ pos 2)) (ldb (byte 8 16) int))
  (setf (aref arr (+ pos 3)) (ldb (byte 8 24) int)))

但是,我不知道如何为 64 位或 8 字节执行此操作 双 float ?假设是小端。

=============

我找到了一个解决方案(使用外部库); https://www.quicklisp.org/beta/UNOFFICIAL/docs/ieee-floats/doc/index.html 使用这个,我可以使用适当的方式将双 float 编码/解码为整数 大小。

最佳答案

从维基百科我们得到 this :

enter image description here

enter image description here

你可以用quicklisp获取你在评论中提到的库:

CL-USER> (ql:quickload 'ieee-floats)
To load "ieee-floats":
  Install 1 Quicklisp release:
    ieee-floats
; Fetching #<URL "http://beta.quicklisp.org/archive/ieee-floats/2015-06-08/ieee-floats-20150608-git.tgz">
; 4.92KB
==================================================
5,041 bytes in 0.01 seconds (378.68KB/sec)
; Loading "ieee-floats"
[package ieee-floats]
(IEEE-FLOATS)
CL-USER> (ieee-floats:encode-float32 23d2)
1158660096
CL-USER> (ieee-floats:decode-float32 #b010101)
2.9427268e-44
CL-USER> (ieee-floats:encode-float32 0)
; Evaluation aborted on #<TYPE-ERROR expected-type: FLOAT datum: 0>.
CL-USER> (ieee-floats:encode-float32 0.0)
0
CL-USER> (ieee-floats:encode-float32 0.1)
1036831949

你当然可以使用 iee-floats:encode/decode-float64 当然,

您还需要知道 #b010101 是一个宏,它表示您可以在普通数学中使用普通 lisp 的二进制数字:

CL-USER> (+ 2 #b10)
4

所以它会为您将二进制转换为整数,然后您也可以使用格式的实用程序

(format nil "~B" 2)
"10"

你可以用来将整数转换为二进制字符串,最后你唯一需要注意的是二进制数字前的 0 自动完成,IEEE 库将它们移除以表示

CL-USER> (ieee-floats:encode-float64 1.0d0)
4607182418800017408
CL-USER> (format nil "~B" *)
"11111111110000000000000000000000000000000000000000000000000000"
CL-USER> (length *)
62
CL-USER> (ieee-floats:encode-float64 -1.0d0)
13830554455654793216
CL-USER> (format nil "~B" *)
"1011111111110000000000000000000000000000000000000000000000000000"
CL-USER> (length *)
64

CL-USER> (ieee-floats:decode-float64 #b11111111110000000000000000000000000000000000000000000000000000 )
1.0d0
CL-USER> (ieee-floats:decode-float64 #b1011111111110000000000000000000000000000000000000000000000000000 )
-1.0d0
CL-USER> (ieee-floats:decode-float64 #b0011111111110000000000000000000000000000000000000000000000000000 )
1.0d0

有了这个,你可以进行所有需要的转换,祝你好运

关于lisp - 如何在普通 lisp 中将 double-float 转换为字节数组,反之亦然?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32622427/

相关文章:

common-lisp - 根据循环中的输出创建一个列表

lisp - 在 Lisp 中调用另一个重载方法

lisp - 将列表中每个列表的第三个元素相加

方案参数检查器错误处理

scheme - (define (add x y) (+ x y)) 和 (define add (lambda (x y) (+ x y))) 有什么区别?

clojure - Clojure 比其他 lisps 的同音性更低吗?

list - 如何在 Common Lisp 中从现有列表中设置某些内容

lisp - 为什么我们需要 Lisp 中的 funcall?

http - 使用 Common Lisp 提供静态文件

lisp - 负载提升包出现问题