Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Length of float changes between 32 and 40 bit

I encountered an odd problem when exporting float values to a file. I would expect every float to be of the same length (obviously), but my programme sometimes exports it a 32 bit number and sometimes as a 40 bit number. A minimal working example of a programme that still shows this behaviour is:

#include <stdio.h>

const char* fileName = "C:/Users/Path/To/TestFile.txt";
float array [5];

int main(int argc, char* argv [])
{
    float temp1 = 1.63006e-33f;
    float temp2 = 1.55949e-32f;

    array[0] = temp1;
    array[1] = temp2;
    array[2] = temp1;
    array[3] = temp2;
    array[4] = temp2;

    FILE* outputFile;
    if (!fopen_s(&outputFile, fileName, "w")) 
    {
        fwrite(array, 5 * sizeof(float), 1, outputFile);
        fclose(outputFile);
    }

     return true;
}

I would expect the output file to contain exactly 20 (5 times 4) bytes, each four of which represent a float. However, I get this:

 8b 6b 07 09      // this is indeed 1.63006e-33f 
 5b f2 a1 0d 0a   // I don't know what this is but it's a byte too long
 8b 6b 07 09      
 5b f2 a1 0d 0a   
 5b f2 a1 0d 0a 

So the float temp2 takes 5 bytes instead of four, and the total length of he file is 23. How is this possible?! The number aren't so small that they are subnormal numbers, and I can't think of any other reason why there would be a difference in size.

I am using the MSVC 2010 compiler on a 64-bit Windows 7 system.

Note: I already asked a very similar question here, but when I realised the problem was more general, I decided to repost it in a more concise way. QDataStream uses sometimes 32 bit and sometimes 40 bit floats

like image 454
Yellow Avatar asked Apr 02 '13 15:04

Yellow


2 Answers

The problem is that on Windows, you have to differentiate between text and binary files. You have the file opened as text, which means 0d (carriage-return) is inserted before every 0a (line-feed) written. Open the file like this:

if (!fopen_s(&outputFile, fileName, "wb"))

The rest as before, and it should work.

like image 139
Angew is no longer proud of SO Avatar answered Nov 08 '22 08:11

Angew is no longer proud of SO


You're not writing text; you're writing binary data... However, your file is open for writing text ("w") instead of writing binary ("wb"). Hence, fwrite() is translating '\n' to "\r\n".

Change this:

if (!fopen_s(&outputFile, fileName, "w")) 

To this:

if (!fopen_s(&outputFile, fileName, "wb")) 

In "wb", the b stands for binary mode.

like image 38
autistic Avatar answered Nov 08 '22 07:11

autistic