The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> C Programming
|
Weird Problem: Hex representation of a float NOT RIGHT!
Discuss Weird Problem: Hex representation of a float NOT RIGHT! in the C Programming forum on Dev Shed. Weird Problem: Hex representation of a float NOT RIGHT! C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

March 24th, 2004, 09:16 AM
|
|
Contributing User
|
|
Join Date: Mar 2004
Posts: 74
Time spent in forums: < 1 sec
Reputation Power: 10
|
|
|
Weird Problem: Hex representation of a float NOT RIGHT!
I have this super annoying problem right now. I'm writing a small program that is supposed to write out a few floats in their hexadecimal representation into an output file.
When I attempt to write, on one line, the hex representation and then the decimal representation of the same float, it doesn't give the correct numbers.
However, if I simply attempt to write the decimal representation alone of the float, it writes it just fine.
It is only when I want to write both the hex and decimal representation at the same time when it messes up. My code is below:
Code:
#include <stdio.h>
int main(void)
{
float timeStamp = 0;
FILE *theFile = fopen("test_file.dat", "w");
do
{
fprintf(theFile, "0x%08x = %.6f\n", timeStamp, timeStamp);
//fprintf(theFile, "%.6f\n", timeStamp);
printf("%.6f\n", timeStamp);
timeStamp = timeStamp + 0.005;
} while(timeStamp <= 0.010);
fclose(theFile);
printf("[Program Complete]\n");
fflush(stdin);
getchar();
return 0;
}
As the code is now, when it is run, the following is the contents the console:
0.000000
0.005000
0.010000
[Program Complete]
and the following is the contents of my output file:
0x00000000 = 0.000000
0x40000000 = 2.000000
0x40000000 = 2.000000
If I uncomment the second fprintf line and comment out the first fprintf line, the following is the contents of the console:
0.000000
0.005000
0.010000
and the following is the contents of my output file:
0.000000
0.005000
0.010000
What the blazes is going on?????
|

March 24th, 2004, 09:24 AM
|
 |
Renaissance Redneck
|
|
Join Date: Jan 2004
Location: Central New York. Texan via Arizona, out of his element!
|
|
|
Becaude %x (or %X) expects an integer as an argument, and %f expects a float. A float is stored as a special binary representation of a number: sign, exponent, and mantissa. Doesn't look at all like an integer.
__________________
Functionality rules and clarity matters; if you can work a little elegance in there, you're stylin'.
If you can't spell "u", "ur", and "ne1", why would I hire you? 300 baud modem? Forget I mentioned it.
DaWei on Pointers Politically Incorrect.
|

March 24th, 2004, 09:27 AM
|
|
Contributing User
|
|
Join Date: Mar 2004
Posts: 74
Time spent in forums: < 1 sec
Reputation Power: 10
|
|
|
Okay, that makes sense. But why is the second representation in the "fprintf(theFile, "0x%08x = %.6f\n", timeStamp, timeStamp);" line still incorrect but when I remove the %08x placeholder, it corrects it?
And is there any way to print the hexadecimal representation of a float?
|

March 24th, 2004, 09:49 AM
|
 |
I'm Baaaaaaack!
|
|
Join Date: Jul 2003
Location: Maryland
|
|
Code:
#include <stdio.h>
int main(){
float fltVal = 123456.78901f;
char *chrPtr = (char *)&fltVal;
int i;
printf("Hex representation of %f: 0x", fltVal);
for (i=0; i<sizeof(float); i++){
printf("%02X", chrPtr[i]);
}
printf("\n");
return 0;
}
Hex representation of 123456.789063: 0x6520FFFFFFF147
As to if this is the true representation, you would have to look up the Intel float docs.
|

March 24th, 2004, 10:22 AM
|
 |
Renaissance Redneck
|
|
Join Date: Jan 2004
Location: Central New York. Texan via Arizona, out of his element!
|
|
|
Unless they've retwisted the data bus since I last looked, the register value (reading MSB to LSB)
Bit 32<-------------------->Bit 0
would be stored little-endian
B7-B0, B15-B8, B23-B16, B31-B24
<--low address high address -->
so you'd need to fetch by decrementing. Personally, to me, that's cattywampus.
|

March 24th, 2004, 10:28 AM
|
 |
Contributing User
|
|
Join Date: Jan 2003
Location: USA
|
|
Quote: | Originally Posted by mitakeet
Code:
#include <stdio.h>
int main(){
float fltVal = 123456.78901f;
char *chrPtr = (char *)&fltVal;
int i;
printf("Hex representation of %f: 0x", fltVal);
for (i=0; i<sizeof(float); i++){
printf("%02X", chrPtr);
}
printf("\n");
return 0;
}
Hex representation of 123456.789063: 0x6520FFFFFFF147
As to if this is the true representation, you would have to look up the Intel float docs. |
Don't forget that Intel's byteorder is little-endian -- I keep getting confused on which is which; the first byte is the least significant byte. As a result, if you try to read multi-byte values from left to right (from lower to higher memory, AKA ++ ), then you will be reading the bytes off backwards.
Google'ing, I rediscovered the name of the standard for floating-point representation: IEEE-754. Trance Sinned should read it to see how floats and doubles are stored. Basically, it's an exponent-and-mantissa representation [i]in binary, so the exponent is powers of two. [disregard]There are two sign bits, one for the entire number and one for the exponent. [/disregard]
One hit, http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html, has a conversion calculator, into which I fed your example:
123456.789063 == 0x47F12065
So your bytes are backwards. And I have no idea where all those extra bytes of 0xFF came from.
Here's some quick-and-dirty code I wrote for a utility:
Code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
float f;
if (argc != 2)
{
fprintf(stderr,"Usage: f2hex <floating-point value>");
exit(1);
}
f = (float)atof(argv[1]);
printf("%g = ",f);
for (i=3; i>= 0; i--) // assumes 4-byte float
printf(" %02X",((unsigned char*)(&f))[i]);
printf("\n");
return 0;
}
Last edited by dwise1_aol : March 24th, 2004 at 12:00 PM.
|

March 24th, 2004, 11:27 AM
|
 |
Renaissance Redneck
|
|
Join Date: Jan 2004
Location: Central New York. Texan via Arizona, out of his element!
|
|
|
Unless they've changed the IEEE 754 specification just recently, there's only one sign bit. The sign of the exponent is a product of a bias in the value. Zero is a special case.
|

March 24th, 2004, 12:01 PM
|
 |
Contributing User
|
|
Join Date: Jan 2003
Location: USA
|
|
Quote: | Originally Posted by DaWei_M Unless they've changed the IEEE 754 specification just recently, there's only one sign bit. The sign of the exponent is a product of a bias in the value. Zero is a special case. |
You're right. That's what I get for relying on wet-ware memory.
|

March 24th, 2004, 12:13 PM
|
 |
I'm Baaaaaaack!
|
|
Join Date: Jul 2003
Location: Maryland
|
|
|
The extra bytes were from some sort of expansion that printf did. After I cast it to an unsigned char the problem went away.
There is also a special bit representation for positive and negative infinity, doanchano.
|

March 24th, 2004, 02:24 PM
|
 |
Renaissance Redneck
|
|
Join Date: Jan 2004
Location: Central New York. Texan via Arizona, out of his element!
|
|
|
Yeah, the various combinations of zeroes in the mantissa and exponent are specialities, too, like NaN and Quiet NaN. It is said (I haven't thought much about it) that the plus zero and the minus zero make for more accurate complex number calculations.
|

March 24th, 2004, 05:05 PM
|
|
Contributing User
|
|
Join Date: Mar 2004
Posts: 74
Time spent in forums: < 1 sec
Reputation Power: 10
|
|
|
Thanks for the help. I got it now.
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|