Как записать двойное в файл в удобочитаемой форме и прочитать точное двойное обратно? - PullRequest
4 голосов
/ 30 сентября 2019

Можно ли записать в файл произвольный дубль в удобочитаемой для человека форме и получить точно , все 64-битные одинаковые двойные при чтении обратно?

Конечно, это возможно путем записи двойного числа в виде двоичных данных, например:

static void writedouble(FILE *fp, double d) {
    fwrite(&d, sizeof(double), 1, fp);
}

Но это не то, что я хочу. Я хочу, чтобы double было написано в удобочитаемой форме, например, так:

static void writedouble(FILE *fp, double d) {
    fprintf(fp, "%.14g", d);
}

А затем снова прочитать его, например, так:

static void readdouble(FILE *fp, double *d) {
    fscanf(fp, "%.14g", d);
}

После этого яхотите проверить, одинаковы ли оба double, например:

printf("Check: %d\n", memcmp(&in_double, &out_double, sizeof(double));

Возможно ли это вообще или возможно получить только битовый double при сохранении его в виде двоичных данных?

Ответы [ 2 ]

3 голосов
/ 30 сентября 2019

Можно ли записать произвольный дубль в читабельном виде в файл и получить точно все 64-битные одинаковые двойники при чтении его обратно?

Да, изКонечно, если вы используете достаточно точности. A double имеет не более DBL_DECIMAL_DIG десятичных знаков точности, как определено в float.h, поэтому следующая программа прекрасно работает:

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <float.h>

static void writedouble(FILE *fp, double d) {
    fprintf(fp, "%.*g", DBL_DECIMAL_DIG, d);
}

static void readdouble(FILE *fp, double *d) {
    fscanf(fp, "%lg", d);
}

int main(void) {
    FILE *fp = fopen("test.txt", "w+");

    double x = M_PI; // Use pi, just as a test.
    double y;

    writedouble(fp, x);
    rewind(fp);
    readdouble(fp, &y);
    fclose(fp);

    // Check if the actual representation of the two values
    // in memory is exactly the same.
    assert(memcmp(&x, &y, sizeof(double)) == 0);

    return 0;
}

Основное различие междувыше, и ваш код таков:

  1. printf вызывается с точностью DBL_DECIMAL_DIG (17), а не 14.
  2. scanf вызываетсябез модификатора точности (поскольку он не нужен и не поддерживается), но с модификатором l, поскольку (в отличие от printf) scanf различает float (f, e, gdouble (lf, le, lg).
1 голос
/ 30 сентября 2019

Другая возможность - это %a формат printf и scanf. Это текст, который на 100% обратим, хотя в отделе читабельности он несколько страдает.

...