Need Fastest Way to Convert 2'S Complement to Decimal in C
I Have a Certain 18 Bits (Which Are in 2'S Complement) Within 32 Bits. I Need to Convert Them to Decimal. Please Show Me a Code Snippet in C. 2 3 Answers First...
I have a certain 18 bits (which are in 2's complement) within 32 bits. I need to convert them to decimal. Please show me a code snippet in C.
3 Answers
First you need to do sign extension on your 18 bits, to fill out the native int:
const int negative = (smallInt & (1 << 17)) != 0;
int nativeInt;
if (negative)
nativeInt = smallInt | ~((1 << 18) - 1);
else
nativeInt = smallInt;
If the number is considered negative (i.e. bit 17 is set), we bitwise-or it with a bit pattern that has ones in all the remaining bits. This creates the proper negative native-sized integer.
Then just print the native integer as usual, since you sound as if you need a decimal string representation:
char buf[12];
snprintf(buf, sizeof buf, "%d", nativeInt);
Of course, this last part might not at all match your expectaions; it's not perhaps "fastest". Since you have a limited input range of 18 bits, it's probably possible to come up with something a bit more optimized.
A few ideas:
- Remove the buffer size argument (i.e. use
sprintf()) since we can be quite sure about the maximum number of characters needed. - Since we know the range, use something less general that never checks for values outside the range.
- Use
itoa()if you have it, less general thans*printf()so might be faster.
I've tried this myself and works just fine:
int binTwosComplementToSignedDecimal(char binary[],int significantBits)
{
int power = pow(2,significantBits-1);
int sum = 0;
int i;
for (i=0; i<significantBits; ++i)
{
if ( i==0 && binary[i]!='0')
{
sum = power * -1;
}
else
{
sum += (binary[i]-'0')*power;//The -0 is needed
}
power /= 2;
}
return sum;
}
Sample:
char binary[8] = '10000001';
int significantBits = 8;
int decimal = binTwosComplementToSignedDecimal(binary,significantBits);
Results in
decimal = -127
Here is the code snippet for 16-bit numbers. A similar approach should work for other bit depths. However, I cannot ensure that this is the fastest snippet.
int16_t twosCompToDec(uint16_t two_compliment_val)
{
// [0x0000; 0x7FFF] corresponds to [0; 32,767]
// [0x8000; 0xFFFF] corresponds to [-32,768; -1]
// int16_t has the range [-32,768; 32,767]
uint16_t sign_mask = 0x8000;
// if positive
if ( (two_compliment_val & sign_mask) == 0 ) {
return two_compliment_val;
// if negative
} else {
// invert all bits, add one, and make negative
return -(~two_compliment_val + 1);
}
}