|
-
March 31st, 1999, 04:25 AM
#1
DoubleToHEX!!!Urgent
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
-
March 31st, 1999, 04:48 AM
#2
Re: DoubleToHEX!!!Urgent
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
-
March 31st, 1999, 05:00 AM
#3
Re: DoubleToHEX!!!Urgent
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
-
March 31st, 1999, 05:43 AM
#4
Re: DoubleToHEX!!!Urgent
Hi,
Type double is a real number and has a fractional part.
What happens if there is anything after the decimal point??
-
March 31st, 1999, 08:50 AM
#5
Ok, but you'll lose the fractional part
double myDouble;
CString myString;
myString.Format("%x",(long)myDouble);
-
March 31st, 1999, 09:46 AM
#6
Back to double
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.
-
March 31st, 1999, 02:07 PM
#7
Re: DoubleToHEX!!!Urgent
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;
}
-
March 31st, 1999, 03:52 PM
#8
Re: DoubleToHEX!!!Urgent
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
-
March 31st, 1999, 05:42 PM
#9
Re: DoubleToHEX!!!Urgent
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
-
March 31st, 1999, 06:29 PM
#10
Re: DoubleToHEX!!!Urgent
Ok. You beat me :-()
Hey wait a minute...my method can't overflow!
Regards,
Paul
-
March 31st, 1999, 06:46 PM
#11
Re: DoubleToHEX!!!Urgent
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
-
March 31st, 1999, 08:04 PM
#12
Re: DoubleToHEX!!!Urgent
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.
-
April 1st, 1999, 01:13 PM
#13
A More General Method
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.
-
April 1st, 1999, 02:07 PM
#14
Re: A More General Method
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
-
April 1st, 1999, 02:16 PM
#15
Re: A More General Method
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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|