Каков наилучший метод для чтения double из двоичного файла, созданного на C?

StackOverflow https://stackoverflow.com/questions/631607

  •  08-07-2019
  •  | 
  •  

Вопрос

Программа на языке Си выдает последовательные удвоения в двоичный файл.Я хочу перевести их на Python.Я пробовал использовать struct.unpack('d',f.read(8))

Редактировать:Я использовал следующее на C для записи случайного двойного числа

r = drand48();
fwrite((void*)&r, sizeof(double), 1, data);

Ошибки теперь исправлены, но я не могу прочитать первое значение.за все 0.000..номер читается как 3.90798504668055, но остальные в порядке.

Это было полезно?

Решение

Я думаю, что вы на самом деле правильно считываете номер, но вас сбивает с толку отображение.Когда я читаю номер из предоставленного вами файла, я получаю "3.907985046680551e-14" - это почти, но не совсем ноль (0.000000000000039 в развернутом виде).Я подозреваю, что ваш C-код просто печатает его с меньшей точностью, чем python.

[Редактировать] Я только что попробовал прочитать файл на C, и я получаю тот же результат (хотя и немного меньшую точность:3.90799e-14) (используя printf("%g", val)), поэтому я думаю, что если это значение неверно, то это произошло на стороне записи, а не чтения.

Другие советы

Не могли бы вы, пожалуйста, поподробнее по поводу "не сработало"?Произошел сбой команды?Были ли получены неверные данные?Что произошло на самом деле?

Если команда завершилась сбоем:

  • Пожалуйста, поделитесь выводом с ошибкой команды

Если данные просто вышли неверными:

  • Имеют ли системы, которые создают и считывают данные, одинаковый порядковый номер?Если один из них имеет порядковый номер, а другой - порядковый номер, то вам нужно указать преобразование в порядковый номер в вашей строке формата.

  • Если порядковый номер двух компьютеров одинаков, как были записаны данные в файл, именно так?Ты знаешь?Если вы это сделаете, то какое значение было записано в файл и какое неверное значение вы получили?

Во-первых, вы пробовали маринованный огурец?Никто еще не показал никакого кода Python...Вот некоторый код для чтения в двоичном формате на python:

import Numeric as N
import array
filename = "tmp.bin"
file = open(filename, mode='rb')
binvalues = array.array('f')
binvalues.read(file, num_lon * num_lat) 
data = N.array(binvalues, typecode=N.Float)   

file.close()

Где f здесь указано с одинарной точностью, 4-байтовые числа с плавающей запятой.Найдите размер ваших данных для каждой записи и используйте его.

Для недвоичных данных вы могли бы сделать что-то простое вроде этого:

   tmp=[]
   for line in open("data.dat"):
                tmp.append(float(line))
  • f.read(8) может возвращать менее 8 байт
  • Данные могут иметь различное выравнивание и / или порядковый номер:

    >>> for c in '@=<>':
    ...     print repr(struct.pack(c+'d', -1.05))
    ...
    '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf'
    '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf'
    '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf'
    '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd'
    >>> struct.unpack('<d', '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd')
    (-6.0659880001157799e+066,)
    >>> struct.unpack('>d', '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd')
    (-1.05,)
    

В Лучшие метод состоял бы в использовании текстового файла ASCII:

0.0
3.1416
3.90798504668055

в том смысле, что он был бы переносимым и в определенной степени работал бы с любым видом реализации с плавающей запятой.

Чтение необработанных двоичных данных из doubleадрес памяти 's вообще не переносим и неизбежно приведет к сбою в какой-то другой реализации.

Конечно, вы можете использовать двоичный формат для компактности, но переносимая функция C, записываемая в этом формате, вообще не будет похожа на ваш фрагмент.

По крайней мере, код должен быть окружен рядом ifs / ifdefs, проверяющих, что представление в памяти doubles, используемые текущей машиной, в точности соответствуют тем, которые ожидаются интерпретатором Python.

Написать такой код было бы непросто, вот почему я предлагаю простое, чистое, переносимое и удобочитаемое решение для ASCII-текста.

Это было бы мой определение понятия "лучший".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top