c - 如何以人类可读的形式将 double 写入文件并读回确切的 double?

标签 c floating-point double

是否可以将人类可读形式的任意 double 写入文件并在读回时完全所有 64 位都是相同的 double ?

当然,这可以通过将 double 写成二进制数据来实现,例如:

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

最佳答案

Is it possible to write an arbitrary double in human-readable form to a file and get exactly, all 64 bits the same double when reading it back in?

是的,当然是,前提是你使用足够的精度。 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, g) 和double (lf, le, lg).

关于c - 如何以人类可读的形式将 double 写入文件并读回确切的 double?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58169989/

相关文章:

java - 如果使用 double 将一种货币值与另一种货币值相互转换,可能会损失的最大精度是多少?

java - 使用 Hector 从 Cassandra 检索(负) double 值会给出错误的结果

c - 查找最长的重复字符串及其在给定字符串中重复的次数

c++ - 使用 MS Visual C++ 2010 'sys/resource.h' : No such file 编译 C

不能输入 double。为什么?

c - float 在 C 中的表示

JavaScript整数除法导致 float ,是否可能出现舍入错误?

c - 嵌套线程创建期间的数据竞争

c++ - 使用 LVM_SORTITEMSEX 将所有选定项目移动到特定项目下方

c++ - 整数在 float 中的精确表示