← Архив: Common Lisp

Считывание вещественных чисел из бинарного файла

Author: · 06.10.2012 17:27
· original author: podymfrombryansk
Здравствуйте. Мне нужно в открытом бинарном файле считать несколько вещественных чисел, каждое число размером 4 байта. Однако если делаю через read-byte, а затем соединяю биты, то получается просто огромное целое число. Приведение типов просто добавляет ноль после запятой. Подскажите, есть ли какие-нибудь стандартные функции, решающие эту проблему. Или вручную перебирать биты и собирать число (собственной функцией) ?
· original author: EO
По-моему, таких нет, так что придётся ручками. Тут вот http://www.mombu.com/programming/lisp/t-converting-bits-to-float-695798.html товарищ Зибель даже свой велосипед показал по аналогичному поводу.
· original author: archimag
В https://github.com/archimag/mongo-cl-driver/blob/master/src/bson/decode.lisp у меня есть функции  decode-int32.
· original author: podymfrombryansk
Спасибо. А что за макрос такой iter? В Вашем файле он не определён.
· original author: archimag
http://common-lisp.net/project/iterate/
· original author: LinkFly
Можно использовать userial
· original author: podymfrombryansk
Спасибо !!! Хорошая библиотека, даже есть в quickload. Сейчас пытаюсь в ней разобраться.
· original author: podymfrombryansk
Появились проблемы с userial. Написал подобный код для сериализации вещественных чисел. Сериализация вроде работает, однако десериализация даёт немного неожиданный эффект - мало того, что она добавляет в передаваемый буфер "мусорные" значения, так ещё и добавляет туда NIL, из-за которого появляется основная ошибка. Вот мой код, подскажите пожалуйста, что не так:(ql:quickload "userial")
(defvar buf (make-array 4 :fill-pointer 0))
(defun f (n)   
  (do () ((= (length buf) 0)) 
  (vector-pop buf))
  (userial:with-buffer buf
    (userial:serialize :float32 n)))
(defun g ()
  (userial:with-buffer buf
    (userial:unserialize :float32)))
· original author: LinkFly
Во-первых: а если попробовать (make-array 4 :fill-pointer 0 :element-type '(unsigned-byte 8))? Или лучше сразу использовать make-buffer из userial. Так же логичней и правильней - никого nil там не должно быть.
Во-вторых: перед десериализация buf fill-pointer точно установлен в конце?
В-третьих, если не поможет: как вызываются f и g
· original author: podymfrombryansk
Так, сейчас вроде добавил userial:make-buffer, но ситуация сильно не улучшилась. Теперь имею следующее:(ql:quickload "userial")
(defun f (n)
  (userial:with-buffer (userial:make-buffer) 
    (userial:serialize :float32 n)))
(defun g (buf)
  (userial:with-buffer buf
    (userial:unserialize :float32)))
(setf x (f 345.623))
(g x)
Функция g использует множественный возврат значений - всегда возвращает 0.0, а в передаваемый буфер дописывает нули. В общем, откуда-то берутся нули, хотя сериализация по-прежнему работает правильно, я проверил, переведя число вручную.
· original author: podymfrombryansk
Ой, и правда, надо было заполнитель на 0 выставить (перед десериализацией) . Спасибо !!!