铸造漂浮的问题 - >当fread时,在C中加倍

时间:2010-07-16 01:07:25

标签: c++ c file-io

我有一个问题,在fread时从float转换为double;

fread(doublePointer,sizeofFloat,500,f);

如果我将双指针更改为浮点指针,它就可以正常工作。 但是,我需要它是laster on的双指针,我想当我从小数据类型(float)写入更大的数据类型(double)的内存时,它应该没问题。但事实证明它不像我预期的那样有效。 这有什么问题,我该如何解决这个问题。

我知道我可以通过逐个转换来解决它。但我有大量的数据。我不想额外9000000+轮转换..这将是非常昂贵的。有什么技巧可以解决吗?

有没有c ++ / c技巧

感谢

4 个答案:

答案 0 :(得分:6)

如果你将float格式的数据写入double,那么你只会得到垃圾。当然,你不会溢出你的缓冲区,但这不是唯一的问题 - 它仍然会找到两个浮点数,它期望一个双倍。你需要将它作为一个浮点读取,然后转换 - 以这种方式转换(甚至隐式)让编译器知道数据最初是一个浮点数并且需要转换:

float temp[500];
int i;

fread(temp, sizeof(temp[0]), 500, f);
for (i = 0; i < 500; i++)
    doublePointer[i] = temp[i];

答案 1 :(得分:3)

假设您的计算机上有一个浮点数为4个字节。如果您读取500个浮点数,那么您将读取2000个字节,每个浮点数一个浮点数,结果是正确的。

假设您的计算机上有一个双字节为8个字节。如果您读取500个浮点数,那么您读取2000个字节,但是您将它们读取为250个双精度数,每个双精度数为2个浮点数,结果是无意义的。

如果您的文件有500个浮点数,则必须读取500个浮点数。将每个浮点值转换为double值。您可以通过这种方式转换每个数值。

当你滥用指针,假装指针指向一个它并不真正指向的数据类型时,那么你不是要转换每个数值,而是保留废话作为无意义。

编辑:你添加了你的问题“我不想额外9000000+轮转换..这将是非常昂贵的。有什么技巧我可以解决它?”答案是肯定的,你可以使用一种把你的花车作为花车的技巧。如果你不想转换为双打,那么不要转换为双打,只需将你的花车保存为花车。

答案 2 :(得分:1)

从浮动到双倍的9000000转换是没有的。 fread放入float数组,然后将其转换为double数组。

科学地对这些代码进行基准测试,不要猜测减速可能在哪里。

如果您在转换时遇到瓶颈,请编写展开的矢量化转换循环,或使用商业矢量库中的循环。

如果它仍然太慢,请将您的读取平铺,以便您在浮动数据中读取适合L1缓存的几页,然后将它们转换为double,然后读取下几页并将其转换为double等等

如果仍然太慢,请调查懒惰地加载数据,以便只加载所需的部分,并且只有在使用它们时才会加载。

现代x86核心能够在手动调整的矢量化循环中每个周期进行两次float->double次转换;在2GHz,每核心每秒40亿次转换。 900万次转换是一个很小的变化 - 我的笔记本电脑在不到1毫秒的时间内完成。


或者,只需将整个数据集转换为double一次,然后从现在开始以这种方式读取它。问题解决了。

答案 3 :(得分:0)

我会从不同的角度来看待这个问题。如果数据存储为float,那么这就是它将拥有的所有精度。在浮点运算规则要求之前,转换为double毫无意义。

所以我会为500(或其他)float分配一个缓冲区,并通过一个适当的fread()调用从数据文件中读取它们:

float *databuffer;
//...
databuffer = malloc(500 * sizeof(float));
fread(databuffer, sizeof(Float), 500, f);

稍后,使用所需的数学数据。如果需要,它将被提升为double。不要忘记在不再需要缓冲区后最终释放缓冲区。

如果你的结果确实具有double的所有精度,那么使用double的新缓冲区来保存它们。但是,如果要将它们作为float写回文件,那么最终需要将它们放入float s的缓冲区中。

请注意,读取和写入用于交换的文件通常需要被视为与内存中数据的有效存储和使用有关的单独问题。通常需要读取文件并以某种方式处理每个单独的值。例如,可能需要便携式程序来处理由系统使用不同字节顺序写入的数据。今天不太常见,您可能会发现即使float中位的布局也不同。一般来说,这个问题通常最好通过推迟实现标准的库来解决,例如XDR(由RFC 4506定义),旨在处理二进制可移植性。