Impresión de archivos binarios y precisión deseada
-
24-09-2019 - |
Pregunta
Estoy imprimiendo una variable Say Z1, que es una matriz 1-D que contiene números de punto flotante en un archivo de texto para que pueda importar a MATLAB o Gnuplot para trazar. He oído que los archivos binarios (.dat) son más pequeños que los archivos .txt. La definición que uso actualmente para imprimir en un archivo .txt es:
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);
}
Tengo tres preguntas:
¿Son los archivos binarios realmente más compactos que los archivos de texto?;
En caso afirmativo, me gustaría saber cómo modificar el código anterior para poder imprimir los valores de la matriz Z1 en un archivo binario. He leído que Fprintf tiene que ser reemplazado por FWrite. Mi archivo de salida dice Dodo.dat debe contener los valores de la matriz Z1 con un número flotante por línea.
Tengo %.16le arriba en mi código, pero creo que %.15le es correcto ya que tengo 15 dígitos de precisión con doble largo. He puesto un punto (.) En la posición de ancho, ya que creo que esto permite la expansión a un campo arbitrario para contener el número deseado. ¿Estoy en lo cierto? Como ejemplo con %.16LE, puedo tener una salida como 1.0047914240730432E-002 que me da 16 dígitos de precisión y el ancho del campo tiene el ancho correcto para mostrar el número correctamente. ¿Es una buena práctica colocar un punto (.) En la posición de ancho en lugar de un valor de ancho?
Muchas gracias...
ACTUALIZAR Está cambiando a:
for(i = 0; i < z_size; i++)
fwrite(&z1, sizeof(long double), 1, out);
ok además del cambio a "wb+"? No puedo leer el archivo binario en MATLAB.
Solución
Sí, los archivos binarios son más compactos, pero pierde la portabilidad y también hay varios otros problemas potenciales, por lo que a menos que sus archivos de datos sean problemáticamente enormes o lentos para exportar/importar, es una buena idea seguir con el texto si puede (usted (usted siempre puede comprimirlos para almacenamiento, por ejemplo, con zip)
Abra su archivo con "WB" en lugar de "W" y use
fwrite()
- Ya no tiene "líneas" en su archivo, solo será un flujo de valores de punto flotante (binarios)Puede que te confundas entre
double
ylong double
- along double
puede tener hasta 16 bytes de tamaño y tener una precisión de hasta alrededor de 32 dígitos (sin embargo, esto depende de la implementación: el doble largo puede ser comúnmente 10, 12 o 16 bytes). Adouble
suele ser 8 bytes y tiene una precisión de alrededor de 16 dígitos.
Es posible que Matlab no pueda hacer frente a long double
(Como no está bien estandarizado), por lo que probablemente solo desee escribir dobles en su archivo de datos, por ejemplo,
for (i = 0; i < z_size; i++)
{
double z = (double)z1[i];
fwrite(&z, sizeof(double), 1, out);
}