Печать двоичных файлов и желаемая точность
-
24-09-2019 - |
Вопрос
Я печатаю переменную, скажем, z1, которая представляет собой одномерный массив, содержащий числа с плавающей запятой, в текстовый файл, чтобы я мог импортировать ее в Matlab или GNUPlot для построения графика.Я слышал, что двоичные файлы (.dat) меньше файлов .txt.Определение, которое я сейчас использую для печати в файл .txt:
void create_out_file(const char *file_name, const long double *z1, size_t z_size){
FILE *out;
size_t i;
if((out = _fsopen(file_name, "w+", _SH_DENYWR)) == NULL){
fprintf(stderr, "***> Open error on output file %s", file_name);
exit(-1);
}
for(i = 0; i < z_size; i++)
fprintf(out, "%.16Le\n", z1[i]);
fclose(out);
}
У меня есть три вопроса:
Действительно ли двоичные файлы более компактны, чем текстовые файлы?;
Если да, я хотел бы знать, как изменить приведенный выше код, чтобы можно было распечатать значения массива z1 в двоичный файл.Я читал, что fprintf нужно заменить на fwrite.Мой выходной файл говорит, что dodo.dat должен содержать значения массива z1 с одним плавающим числом в строке.
В моем коде есть %.16Le, но я думаю, что %.15Le правильный, поскольку у меня 15 точных цифр с длинным двойным числом.Я поставил точку (.) в позиции ширины, так как считаю, что это позволяет расширить произвольное поле для хранения желаемого числа.Я прав?В качестве примера с %.16Le я могу получить вывод типа 1.0047914240730432e-002, который дает мне 16 точных цифр, а ширина поля имеет правильную ширину для правильного отображения числа.Является ли размещение точки (.) в позиции ширины вместо значения ширины хорошей практикой?
Большое спасибо...
ОБНОВЛЯТЬ Меняется на:
for(i = 0; i < z_size; i++)
fwrite(&z1, sizeof(long double), 1, out);
ок, в дополнение к изменению на «wb+»?Я не могу прочитать двоичный файл в Matlab.
Решение
да, двоичные файлы более компактны, но вы теряете переносимость, а также возникают различные другие потенциальные проблемы, поэтому, если ваши файлы данных не слишком велики или не медленно экспортируются/импортируются, рекомендуется придерживаться текста, если вы можете (вы всегда можно сжать их для хранения, например.с молнией)
откройте файл с помощью «wb» вместо «w» и используйте
fwrite()
- в вашем файле больше нет "строк" - это будет просто поток (двоичных) значений с плавающей запятойвы, возможно, путаетесь между
double
иlong double
- аlong double
может иметь размер до 16 байт и точность примерно до 32 цифр (однако это зависит от реализации - long double обычно может иметь длину 10, 12 или 16 байт).Аdouble
обычно имеет размер 8 байт и точность около 16 цифр.
MATLAB, возможно, не сможет справиться с long double
(поскольку он не очень хорошо стандартизирован), поэтому вы, вероятно, просто захотите записать двойники в свой файл данных, например.
for (i = 0; i < z_size; i++)
{
double z = (double)z1[i];
fwrite(&z, sizeof(double), 1, out);
}