Click to See Complete Forum and Search --> : DoubleToHEX!!!Urgent
vittal
March 31st, 1999, 03:25 AM
Hi,
Is there any built-in function which can convert a double value into a hexadecimal value and back.
OR is there any other way of doing it.
Please help me ASAP, its very urgent.
Thanks in Advance
Vittal
Rail Jon Rogut
March 31st, 1999, 03:48 AM
How about something simple like:
CString DecimalToHex(DWORD dwValue)
{
BOOL bFlag = TRUE;
CString szReturn;
CString szLetter;
float fRemainder;
unsigned long lTemp, lTemp2;
lTemp = dwValue;
while (lTemp)
{
lTemp2 = lTemp;
lTemp = lTemp2/16;
fRemainder = ((float)lTemp2/16.0F) - (float)lTemp;
lTemp2 = (long)(fRemainder * 16.0F);
if (lTemp2 > 9)
{
switch (lTemp2)
{
case 10: szLetter = "A";
break;
case 11: szLetter = "B";
break;
case 12: szLetter = "C";
break;
case 13: szLetter = "D";
break;
case 14: szLetter = "E";
break;
case 15: szLetter = "F";
break;
}
}
else
szLetter.Format("%d", lTemp2);
szReturn += szLetter;
}
szReturn.MakeReverse();
return szReturn;
}
Please excuse the formatting... the BBS has been changing my formatting tonite.
Rail
Recording Engineer/Software Developer
Rail Jon Rogut Software
Rail Jon Rogut Software
Rail Jon Rogut
March 31st, 1999, 04:00 AM
Of course, besides that other method, there's always:
CString szTemp;
DWORD dwTemp = 4290384468;
szTemp.Format("%lX", dwTemp);
which sets szTemp equal to: FFBA1254
Rail
Recording Engineer/Software Developer
Rail Jon Rogut Software
Rail Jon Rogut Software
Orlando
March 31st, 1999, 04:43 AM
Hi,
Type double is a real number and has a fractional part.
What happens if there is anything after the decimal point??
Bore
March 31st, 1999, 07:50 AM
double myDouble;
CString myString;
myString.Format("%x",(long)myDouble);
Bore
March 31st, 1999, 08:46 AM
Sorry, I missed the "and back" part of your question. From the original example:
double myDouble;
CString myString;
char *dummy;
myString.Format("%x",(long)double);
myDouble = (double)strtol((LPCTSTR)myString,&dummy,16);
Of course, you'll never get the fractional part back. And I didn't mention it before, but of course, you'll also lose
data if the value of the double is greater than 2^32.
Gomez Addams
March 31st, 1999, 01:07 PM
This really made me curious. I decided to try a back-door approach.
The key is using a union to share the eight bytes of a double with
a 64-bit integer so sscanf and sprintf can take of the conversions.
I actually compiled this and it runs.
typedef union
{
__int64 intval;
double dblval;
} DIUNION;
int main( int ac, char *av[] )
{
// should verify that there is an argument
double dval = atof( av[1] );
printf( "original is : %.6f\n", dval );
DIUNION diu1;
diu1.dblval = dval;
char buffer[32];
sprintf( buffer, "%016I64X", diu1.intval );
printf( "hex string is %s\n", buffer );
DIUNION diu2;
sscanf( buffer, "%I64X", &diu2.intval );
printf( "double val is %.6f\n", diu2.dblval );
return 0;
}
Paul McKenzie
March 31st, 1999, 02:52 PM
The trick is to convert floating point decimal to hex is to do the following:
0) Convert the integer portion of the number to hex. Append a decimal point.
Store this result in "sub-answer".
1) Take the decimal portion of the original number (the digits after the
decimal point). Include the decimal point (this is very important!). Call
this number the "decimal portion".
2) multiply this decimal portion by 16.
3) strip the integer portion of the answer you got for 2) and append to "sub-
answer in 1).
4) Exhausted? Stop.
5) Use the stripped integer answer you got for step 3 and that is your new
decimal portion. Go to step 2
Example:
25.48 to hex
Step 0) 25 = 0x19.
Step 1) .48
Step 2) .48 x 16 = 7.68
Step 3) 0x19. --> 0x19.7 (got the 7 from step 2)
Step 4) Not tired. keep going
Step 5) Use the .68 and do step 2
Step 2) .68 x 16 = 10.88
Step 3) 0x19.7 --> 0x19.7A (I converted the 10 to the hex A)
Step 4) Not tired.
Step 5) Use the .88 and goto step 2
Step 2) .88 x 16 = 14.08
Step 3) 0x19.7A --> 0x19.7AE
Step 4) Tired. Stop
Answer 25.48 is approximately 0x19.7AE
I hope I didn't make any errors :-()
Regards,
Paul
Rail Jon Rogut
March 31st, 1999, 04:42 PM
Oh, then how about:
CString szTemp;
double dwTemp = 25.48;
int iVal = (int)dwTemp;
double iResolution = 4.0; // How many positions after the point
int iVal2 = (int)((dwTemp - (double)iVal) * pow(16.0, iResolution));
szTemp.Format("%X.%X", iVal, iVal2);
Rail
Recording Engineer/Software Developer
Rail Jon Rogut Software
Rail Jon Rogut Software
Paul McKenzie
March 31st, 1999, 05:29 PM
Ok. You beat me :-()
Hey wait a minute...my method can't overflow!
Regards,
Paul
Rail Jon Rogut
March 31st, 1999, 05:46 PM
Hey... didn't know this was a competition... :^)
Actually your method is perfect, similar to the way I posted 2 methods initially
last nite (or this morning)... this was simply another way to get the same results.
As for the overflow... yup, you're right :^)
All the best.
Rail
Recording Engineer/Software Developer
Rail Jon Rogut Software
Rail Jon Rogut Software
Gomez Addams
March 31st, 1999, 07:04 PM
Just to play devil's advocate, what if it's a really
huge number that needs an exponent to display correctly ?
Or, for that matter, a really really small one ?
Personally, I kind of like my method but it is far from
portable since it relies on an __int64. I guess an array
of eight bytes could accomplish the same thing and then
there is only the LSB-MSB issue to worry about.
That is, if anyone really cares about portability.
Who knows, if Linux picks up steam portability could
become much more of an issue.
Gomez Addams
April 1st, 1999, 12:13 PM
I started thinking about this some more and decided the union
with an __int64 wasn't the best option. I revised it so that
there is no union and this will work with any data type. This
should be fairly portable also in case you care. The one caveat
I can think of about this approach is that the hex data will
probably not be completely transportable between different types
machines. This is an issue of little-endian versus big-endian.
Again, this is an 'if you care' issue.
typedef unsigned char uchar;
void ConvertToHex( char *dstbuf, void *pvalue, size_t valsize )
{
*dstbuf = '\0'; // initialize string
// step through each byte of the value
uchar * pchval = (uchar *)pvalue;
for( size_t x = 0; x < valsize; x += 1 )
{
// obtain current byte
uchar itembyte = *pchval;
// load a string with hex value of byte
char tmpbuf[4];
sprintf( tmpbuf, "%02X", itembyte );
// concatenate to destination buffer
strcat( dstbuf, tmpbuf );
pchval += 1;
}
}
void ConvertFromHex( char *srcbuf, void *pvalue, size_t valsize )
{
uchar * pchval = (uchar *)pvalue; // start a first byte
for( size_t x = 0; x < valsize; x += 1 )
{
// determine string index - hex has 2 chars per byte
int chindex = x * 2;
// grab hex string for 1 byte
char tmpbuf[4];
strncpy( tmpbuf, srcbuf + chindex, 2 );
tmpbuf[2] = '\0';
// convert hex string to a byte value
uchar byteval = (uchar)strtol( tmpbuf, NULL, 16 );
// load byte into the destination
*pchval = byteval;
pchval += 1;
}
}
// test the algorithms - what goes in should come out
void main()
{
char buffer[32];
double dblval = 3.1415926539;
printf( "\nvalue is : %.9f\n", dblval );
ConvertToHex( buffer, &dblval, sizeof( double ) );
printf( "hex value : %s\n", buffer );
ConvertFromHex( buffer, &dblval, sizeof( double ) );
printf( "dbl value : %.9f\n", dblval );
int intval = 3563428;
printf( "\nvalue is : %.d\n", intval );
ConvertToHex( buffer, &intval, sizeof( int ) );
printf( "hex value : %s\n", buffer );
ConvertFromHex( buffer, &intval, sizeof( int ) );
printf( "int value : %d\n", intval );
}
PS. Sorry to spoil your fun - I like an occasional challenge.
Rail Jon Rogut
April 1st, 1999, 01:07 PM
Hi Gomez
Your algorithm converts to and from Hex correctly, but you need to shift the bytes around for the display of the Hex value...
Remember when you store the value in memory, it's not gonna be displayed in the same way we humans would want to look at it
For example... You test function sets the value
int intval = 3563428;
and you algorithm converts that to Hex:
A45F3600
which is wrong because of byte ordering...
switch them around and you get the right answer:
A4 5F 36 00 => 00 36 5F A4 .... 0x00365FA4
Your other example:
double dblval = 3.1415926539;
creates the hex value:
B4D54E54FB210940 => 040921FB544ED5B4 (from the above logic)
But that doesn't fall into the format which we expect to see displayed...
(integer).(fraction)
which each digit:
X(n), X(n-1),....X(2), X(1), X(0).Y(-1), Y(-2), ...Y(z+1), Y(z)
and we multiply each digit X or Y by the base to the power of the subscript and sum them all together:
Value = X(0)*pow(Base, 0) + X(1)*pow(Base, 1)+...+X(n)*pow(Base,n) + Y(-1)*pow(Base, -1) + Y(-2)*pow(Base, -2)+...+Y(z)*pow(Base, z)
for instance:
Decimal 25.48
= 2*pow(10, 1) + 5*pow(10, 0) + 4*pow(10, -1) + 8*pow(10, -2)
= 20 + 5 + .4 + .08
= 25.48
convert that to HEX:
Hex 0x19.7AE
= 1*pow(16, 1) + 9*pow(16, 0) + 7*pow(16, -1) + A*pow(16, -2) + E*pow(16, -3)
= 16 + 9 + .0625 + .0390 + .0034
= 25.4799
Anyway...
All the best.
Rail
Recording Engineer/Software Developer
Rail Jon Rogut Software
Rail Jon Rogut Software
Rail Jon Rogut
April 1st, 1999, 01:16 PM
Sorry, I made a typeo:
convert that to HEX:
Hex 0x19.7AE
= 1*pow(16, 1) + 9*pow(16, 0) + 7*pow(16, -1) + A*pow(16, -2) + E*pow(16, -3)
= 16 + 9 + .0625 + .0390 + .0034
= 25.4799
should of course read:
convert that to HEX:
Hex 0x19.7AE
= 1*pow(16, 1) + 9*pow(16, 0) + 7*pow(16, -1) + A*pow(16, -2) + E*pow(16, -3)
= 16 + 9 + .4375 + .0390 + .0034
= 25.4799
I had written .0625 instead of 7 * .0625 which equals .4375
Rail
Recording Engineer/Software Developer
Rail Jon Rogut Software
Rail Jon Rogut Software
April 1st, 1999, 04:17 PM
I remember from my schooldays the method you described can be used to convert
a decimal number to a number of any base/radix. To change to octal you just
multiply be 8 rather than 16....etc...
Andy orlando St.Clair
April 1st, 1999, 04:55 PM
Apparently, there are two schools of thought concerning this question.
Do you want a string representing a double converted to a string representing hex
or a binary double value converted to a string representing hex or what ?
Gomez
PS.- this new board doesn't like me using my 'real' name
Gomez Addams
April 2nd, 1999, 12:57 PM
It seems to me this is a question of 'is a readability important ?'
I assumed that it wasn't. My solution will exactly convert the values
of any data type to and from a hex string. The hex string is written
in the same order that the data appears in memory. I don't consider
it important or even useful to be able to read the hex digits of a floating
point value. The only use I can conceive of for this kind of thing is to
convert binary data into an ASCII representation for storage or
transmission. In this case I think accuracy is the highest priority.
This scheme will even handle data having an enormous dynamic
range like 3.5E201 or -2.6E-199 and use only 16 characters to do
it instead of 400.
Maybe I am reading more into the poster's question than I should.
I did post a question asking them exactly what they were after but
I haven't seen a response. Oh well, different strokes ...
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.