Click to See Complete Forum and Search --> : Convert float to Big Endian


rodman3257
January 29th, 2002, 04:57 PM
Hi.

I want to read a binary file with a big endian sequence. I can convert int, short and long by simply changin bit order. However, I can not convert float & double to Big Endian Sequence. Could you please let me know the method?

Thank you.

thew
January 29th, 2002, 09:46 PM
Files even "binary" files are stored in characters. That means when you write a string to a binary file you're actually writing a character string. Characters are only byte values so no need to worry about big Endian etc.
Check it out..

The big Endian, little Endian issue really comes into play when you're transfering data over a socket between OS's

Transfering datafiles between OS's usually ammounts to handling the end of line and line feeds characters correctly.

jwycoff
January 30th, 2002, 01:58 AM
Hello,
I am a bit confused about your claim that "even binary files are stored in characters" and that you don't have to worry about big Endian, etc. This is in my opinion not correct. Binary files can maintain the memory characterstics of the machine which created it, depending on how the binary file was create. I submit an example program and the output as viewed by a hex editor. This is certainly not a string.

If I misunderstood your explanation, please give a more thorough explanation of how you create the binary files you are talking about, as this has nothing in common with the binary files I use to store binary data.

Best regards.

The output in a hex editor:
00 00 80 3F 00 00 80 BF 60 E5 CF 41




The test program:


int main(int argc, char* argv[])
{
float f1;
FILE* pTestFile= 0;
printf("Writing float to the file testfloat.bin\n");
f1 = 25.987;
pTestFile = fopen("testfloat.bin", "w+b");
if (pTestFile == NULL)
return -1;
f1 = 1.00;
fwrite(&f1, sizeof(float), 1, pTestFile);
f1 = -1.00;
fwrite(&f1, sizeof(float), 1, pTestFile);
f1 = 25.987;
fwrite(&f1, sizeof(float), 1, pTestFile);
fclose(pTestFile);
return 0;
}






Please rate my answer, whether good or bad, so I can improve the answers I give. Thanks!

NMTop40
January 30th, 2002, 04:56 AM
A float and a double are actually stored as bit-maps. float is 32 bit and double is 64 bit and there is a long double which I think is 128 bit.

I think it is standard on all systems.


The best things come to those who rate

jwycoff
January 30th, 2002, 05:31 AM
A modified version of my previous program shows that writing the binary format of the float to a file (using fwrite()) uses the machine's byte ordering scheme.

Here's the new test program (run on an Intel machine):

int main(int argc, char* argv[])
{
float f1;
unsigned int* pInt1;
unsigned char msb1, msb2, msb3, msb4;
FILE* pTestFile= 0;
printf("Writing float to the file testfloat.bin\n");
f1 = 25.987;
pTestFile = fopen("testfloat.bin", "w+b");
if (pTestFile == NULL)
return -1;

f1 = 25.987;
pInt1 = (unsigned int*) &f1;
msb1 = (unsigned char) ((*pInt1) >> 24);
msb2 = (unsigned char) ((*pInt1) >> 16);
msb3 = (unsigned char) ((*pInt1) >> 8);
msb4 = (unsigned char) ((*pInt1) & 0x000000FF);

fwrite(&f1, sizeof(float), 1, pTestFile);
fwrite(&msb1, 1, 1, pTestFile); // Most significant byte
fwrite(&msb2, 1, 1, pTestFile);
fwrite(&msb3, 1, 1, pTestFile);
fwrite(&msb4, 1, 1, pTestFile); // Least significant byte
fclose(pTestFile);
return 0;
}






The hex contents of the file:
60 E5 CF 41 41 CF E5 60

which shows that the float is stored with little-endian byte ordering when the float is supplied as a parameter to fwrite(), but when outputting the single bytes from most significant to least signficant we see the reverse order (like it would be with big-endian).

It would be interesting to see the same program run on a mac or some other machine whose processor uses big-endian byte ordering.

Let me know if I'm getting this completely wrong, but I think that all the issues involved with sending binary data over a socket connection apply just as well to files. They are, after all, both simply serialized forms of the data.

Regards.




Please rate my answer, whether good or bad, so I can improve the answers I give. Thanks!

NMTop40
January 30th, 2002, 06:35 AM
this program would give different results on a big-endian machine, not because of the way it outputs float, but because you cast to unsigned int * and then looked at the results.

So on an LSB 60 E5 CF 41 is one integer and on an MSB it is another.

All you have proved is that Windows is LSB. And it's the operating system, not the processor, that determines the order.



The best things come to those who rate

jwycoff
January 30th, 2002, 07:13 AM
Here's what MSDN says about little-endian byte ordering. There's no mention that Windows handles the byte ordering. Are we even talking about the same thing?
Regards.

-------------------
little-endian
Refers to a processor memory architecture in which the byte layout is as follows:

· Byte N is the least significant (and, in conventional layout diagrams, the "rightmost") byte of:

· A word composed of bytes N and (N + 1).

· A double word composed of bytes N, (N + 1), (N + 2), and (N + 3).

· A K-byte memory entity composed of bytes N, (N + 1),...,(N + K - 1).

The address of the preceding word, double word, or K-byte entity is its least significant byte, N.

Intel microprocessors always support little-endian addressing. Some RISC microprocessors can be configured for either big-endian or little-endian addressing. For a little-endian configuration, the least significant bit of a 16-bit short value is the "rightmost" bit at byte N, while the most significant bit is the "leftmost" bit of byte (N + 1). See also big-endian.



Please rate my answer, whether good or bad, so I can improve the answers I give. Thanks!

thew
January 30th, 2002, 05:18 PM
>> This is in my opinion not correct. Binary
>> files can maintain the memory characterstics
>> of the machine which created it, depending on
>> how the binary file was create

It doesn't matter if the file is a binary file or a text file. You're example has the properties of the processor because that is what fwrite does..It dumps the contents of memory to a file unformated. The binary parameter on the fopen only influences the <CR> or <CR><LF>.

To illistrate my point we can write two files an asscii one and a text one..


int main(int argc, char* argv[])
{
int iVal =100;
float fVal =9.8;
char *pszBuffer = "100 - 9.8";
FILE *stream;

// write the binary file

if( (stream = fopen( "BinData.txt", "w+b" )) == NULL )
{
printf( "The file 'data' was not opened\n" );
return 0;
}
else
{
printf( "The file 'data' was opened\n" );
}

fwrite( &iVal, sizeof( int ), 1, stream );

fprintf( stream, "\n%d - %3.1f\n", iVal, fVal );
fprintf( stream, "%s\n", pszBuffer );

fclose ( stream );

// write the ascii text file

if( (stream = fopen( "TxtData.txt", "w+t" )) == NULL )
{
printf( "The file 'data' was not opened\n" );
return 0;
}
else
{
printf( "The file 'data' was opened\n" );
}

fwrite( &iVal, sizeof( int ), 1, stream );
fprintf( stream, "\n%d - %3.1f\n", iVal, fVal );
fprintf( stream, "%s\n", pszBuffer );

fclose ( stream );
return 0;

}




The output from the BinData.txt file

64 00 00 00 0A 31 30 30 20 2D 20 39 2E 38 0A 31 // <-- d....100 - 9.8.1
30 30 20 2D 20 39 2E 38 0A // <- 00 - 98.




The output from the TxtData.txt file

64 00 00 00 0D 0A 31 30 30 20 2D 20 39 2E 38 0D // <- d.....100 - 9.8.
0A 31 30 30 20 2D 20 39 // <- .100-9.8..




The only difference between the binary file and the assci file being in the <CR> or the <LF>. That was my point..

Now which I think was your point.. if you run the same program on a Solaris box.. which I did.. you will see that the fwrite command does memory dump the int value with the sig digs reversed..

00 00 00 64




But even here for both the binary and ascii files the other bytes remain constant across the platforms and this is because fprintf/cout etc etc.. writes characters to the file and not binary dumps like fwrite. Once again regardless of if the file was "created" with a binary flag or not... and regardless if the file was created on Solaris or NT.

kjetil7
January 31st, 2002, 06:02 AM
Another way of writing as big endian on a little endian machine (Intel):



union FloatBytes {
float FloatValue;
unsigned char Byte[sizeof(float)];
};

FloatBytes f1;
FILE* pTestFile = 0;
int i;

f1.FloatValue = (float) 25.987;

//--- open file
pTestFile = fopen("testfloat.bin", "w+b");
if(!pTestFile) return -1;

//--- write the little endian way..
for(i=0; i<sizeof(float); i++) fwrite(&f1.Byte[i], 1, 1, pTestFile);

//--- write the big endian way..
for(i=sizeof(float)-1; i>=0; i--) fwrite(&f1.Byte[i], 1, 1, pTestFile);

//--- close file
fclose(pTestFile);





Regards,
Kjetil Haga

Michael Tjong
February 15th, 2002, 02:37 PM
f1 = 25.987;
pInt1 = (unsigned int*) &f1;
msb1 = (unsigned char) ((*pInt1) >> 24);
msb2 = (unsigned char) ((*pInt1) >> 16);
msb3 = (unsigned char) ((*pInt1) >> 8);
msb4 = (unsigned char) ((*pInt1) & 0x000000FF);

--------------------------

Hi .. thanks so much for this codes. It helps me a lot in developing my project.
However, I have another question if you can help me which is after a floating point number is converted to an four bytes of unsigned char. How do you reverse to process to read back its floating point number?
Thanks in advance ..

Michael