Каков наилучший метод для чтения double из двоичного файла, созданного на C?
Вопрос
Программа на языке Си выдает последовательные удвоения в двоичный файл.Я хочу перевести их на 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, проверяющих, что представление в памяти double
s, используемые текущей машиной, в точности соответствуют тем, которые ожидаются интерпретатором Python.
Написать такой код было бы непросто, вот почему я предлагаю простое, чистое, переносимое и удобочитаемое решение для ASCII-текста.
Это было бы мой определение понятия "лучший".