从二进制文件读取并转换为双精度文件?

Reading from binary file and converting to double?

我正在尝试编写一个 C 程序来读取二进制文件并将其转换为数据类型。我正在生成一个带有 head 命令 head -c 40000 /dev/urandom > data40.bin 的二进制文件。该程序适用于数据类型 int 和 char,但不适用于 double。这是程序的代码。

void double_funct(int readFrom, int writeTo){
    double buffer[150];
    int a = read(readFrom,buffer,sizeof(double));
    while(a!=0){
        int size = 1;
        int c=0;

         for(c=0;c<size;c++){
            char temp[100];
            int x = snprintf(temp,100,"%f ", buffer[c]);
            write(writeTo, temp, x);
        }
        a = read(readFrom,buffer,sizeof(double));
    }
}

这是有效的 char 函数

void char_funct(int readFrom, int writeTo){
    char buffer[150];
    int a = read(readFrom,buffer,sizeof(char));
    while(a!=0){
        int size = 1;
        int c=0;

        for(c=0;c<size;c++){
            char temp[100]=" ";
            snprintf(temp,100,"%d ", buffer[c]);
            write(writeTo, temp, strlen(temp));
        }
        a = read(readFrom,buffer,sizeof(char));
    }
}

问题是,对于 char,我需要使用 wc -w file 获取 40000 个单词,我得到了它们。现在用 double 我得到随机数量的单词,但理论上我应该从 40000 字节的数据中得到 5000,但我得到 4000 到 15000 之间的随机数量,对于 char 我得到 40000,就像一个字符应该 1 个字节一样。

我不知道有什么问题相同的代码适用于 int,我从 40000 字节的数据中得到 10000 个单词。

主要问题似乎是您的 temp 数组对于您的 printf 格式和数据来说不够大。 IEEE-754 doubles 的十进制指数范围从 -308 到 +308。您正在使用 "%f" 格式打印双打,这会产生一个简单的十进制表示形式。由于未指定精度,因此应用默认精度 6。这可能需要多达 1(符号)+ 309(数字)+ 1(小数点)+ 6(尾随小数位)+ 1(终止符)字符(总共 318),但你只有 space 100.

您使用 snprintf() 打印到您的缓冲区,因此不会超出那里的数组边界,但是 snprintf() returns 将拥有的字节数被要求 ,减去终结者所需的那个。那是您 write() 的字节数,并且在许多情况下 确实 超出了您的缓冲区。您会在输出中看到结果。

其次,您还会在输出中看到大量 0.00000,这是由于将小数字四舍五入到 6-decimal-digit 精度而产生的。

如果您更改打印数字的格式,您可能会取得更大的成功。例如,"%.16e " 将为您提供指数格式的输出,共有 17 位有效数字(小数点前一位)。这不需要内存或磁盘上过多的 space,并且它会准确地传达所有数字,无论比例如何,再次假设您的 double 是按照 IEEE 754 表示的。如果您愿意,您可以此外,通过采用@chux 在评论中建议的变体,进一步消除了 IEEE 754 格式的(相当安全的)假设。那将是最安全的方法。

还有一件事:IEEE 浮点数支持无穷大和多个 not-a-number 值。与普通的 FP 数字相比,这些数字非常少,但您仍然有可能偶尔会碰到其中一个。它们可能会很好地转换为输出,但您可能需要考虑是否需要专门处理它们。