algebra precalculus - How can I convert 2's complement to decimal? - Mathematics Stack Exchange
Need fastest way to convert 2's complement to decimal in C - Stack Overflow
convert 2's complement to decimal
Conversion in decimal of a number expressed in two's complement using 5 bits
What is the two's complement?
The two's complement is a way to represent negative numbers in binary when the minus sign is not available. The minus sign is substituted in the two's complement representation by a digit, usually the leading one.
- If the leading digit is
0, the number is positive. - If the leading digit is
1, the number is negative.
How do I calculate the two's complement of a number?
To calculate the two's complement of a number:
- If the number is negative, subtract it from the power of 2 with exponent corresponding to the number of bits of your chosen representation.
- Convert the number to binary.
- If the number was negative, add
1to the proper position and pad with0. - If the number was positive, left-pad the result with
0to the desired length.
What is the 8-bit two's complement notation of -37?
The 8-bit two's complement representation of −37 is 110110112. To find this result:
- Subtract 37 from 27: 128 − 37 =91.
- Find the binary representation of 91:
91 = 64 + 16 + 8 + 2 + 1
= 1·26 + 0·25 + 1·24 + 1·23 + 0·22 + 1·21 + 1·20
=1011011 - Place 1 in the correct position to mark that we started from a negative number:
−3710 = 110110112
Videos
Here is the process to convert a negative two's complement number back to decimal:
(1) flip all the bits,
(2) add 1, and
(3) interpret the result as a binary representation of the magnitude and add a negative sign
So, for your example, we have:
$$1111~1111~1011~0101 \xrightarrow{(1)} 0000~0000~0100~1010 \xrightarrow{(2)} 0000~0000~0100~1011 \xrightarrow{(3)} -75$$
It looks like you wrote the wrong binary and meant:
$$1111~1111~1011~1011~0101 \xrightarrow{(1)} 0000~0000~0100~0100~1010 \xrightarrow{(2)} 0000~0000~0100~0100~1011 \xrightarrow{(3)} -1099$$
Of course, in Hex, you can invert all the bits and add 1 and take a negative magnitude.
Regards
If is an
digit number written in two's complement, then
, where
is the
-digit binary NOT of
. In your case,
~0xFFBB5 + 1 = 0x0044B = 1099, so your number is $-1099$.
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.
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);
}
}
I have a 12 bit hex number, like this: "fe9". It should be equal to -7.1 in decimal, but I don't know how to convert it. I asked ChatGPT, and it told me to do this:
temp_raw = 0xfe9 temp_c = (temp_raw >> 4) * 0.1 print(temp_c) # Output: -7.1
But instead of outputting -7.1, I get 25.400000000000002. What is the correct way to do this?
The mathematical version:
=-INT(BIN2DEC(A1)/2^4)*2^4+MOD(BIN2DEC(A1),2^4)
where 4 is the number of significant bits.
Andreas.
Thanks a lot Andreas.
the mathematical version is also better since I can also avoid to convert the initial decimal number in binary.
Therefore, having the input data in decimal, it is also possible to use the following one in excel:
=-BITAND(A1;2^4)+BITAND(AV1;2^4-1)
that is probably less expensive in terms of calculations needed.
Best Regards
Here's what he's getting at.
You are correct with the biz "...A=163 B=46,666 in decimal notation..."
That is the unsigned 16 bit interpretation.
If these were signed 16 bit integers, the first one would still be 163, while the second one would be negative 18,870
What they are getting at is that the top bit is the sign bit, which alerts you to the fact that this could be a negative number.
So, the answer is...
- For unsigned numbers: as you have stated,
A=163, B=46,666 - For signed numbers: as I have stated.
A=163, B=-18,870(note, the last one is negative)
If you need me to go into more detail about this, I'll edit this answer and show you the procedure for doing all the change-o-matic steps in two's complement. In fact, I just did this three hours ago in THIS ANSWER here. (Click on it if you need to)
The hex number 0x876 can be considered a positive number 2166 in decimal. But if you consider it to be a signed 12 bit number, the msbit is set, so it is negative. To figure out what the decimal number is, you need to do the invert and add one. Inverting yields 0x789, add one 0x78A which is 1930. So, the decimal representation for that as a negative number (two's complement) is -1930.
Take an even easier one the twelve bit number 0xFFF, unsigned that is 4095, but signed that is invert to 0x000 add one 0x001, -1 in decimal.
Apply that knowledge to the numbers in your question.