Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a signed decimal to hex encoded with two's complement

I need to encode a signed integer as hexadecimal using via the two's complement notation. For example I would like to convert

e.g. -24375 to 0xffffa0c9.

So far I have been working on the following lines:

parseInt(-24375).toString(2)
> "-101111100110111"    

This matches what Wolfram Alpha displays, but I am not sure how to get to the signed 24bit int representation of the number (ffffa0c9).

I've worked out how to take the unsigned binary number and represent this as two's complement:

~ parseInt("101111100110111", 2) + 1
> -23475

but I am not sure get the binary representation of this number to convert to hex.

Any ideas?

like image 563
diffa Avatar asked May 26 '11 23:05

diffa


People also ask

How do you do 2s complement in hexadecimal?

To compute the two's complement of a n-digit hexadecimal numeral, either: complement each digit (exchange 0 for F, 1 for E, and so on) and then add one to the whole numeral, or. subtract the numeral from (In hexadecimal) one followed by n zeroes.

How do you convert to signed two's complement?

To get 2's complement of binary number is 1's complement of given number plus 1 to the least significant bit (LSB). For example 2's complement of binary number 10010 is (01101) + 1 = 01110.

What is hex signed 2's complement?

Two's complement is an agreement how to represent signed integral numbers in e.g. 16 bits (in olden times, different representations have been used by various processors, e.g. one's complement or sign-magnitude). Positive numbers and zero are represented as expected: 0 is 0000 0000 0000 0000 or hex 0000.


2 Answers

Here's a pretty straightforward solution using parseInt :

function DecimalHexTwosComplement(decimal) {
  var size = 8;

  if (decimal >= 0) {
    var hexadecimal = decimal.toString(16);

    while ((hexadecimal.length % size) != 0) {
      hexadecimal = "" + 0 + hexadecimal;
    }

    return hexadecimal;
  } else {
    var hexadecimal = Math.abs(decimal).toString(16);
    while ((hexadecimal.length % size) != 0) {
      hexadecimal = "" + 0 + hexadecimal;
    }

    var output = '';
    for (i = 0; i < hexadecimal.length; i++) {
      output += (0x0F - parseInt(hexadecimal[i], 16)).toString(16);
    }

    output = (0x01 + parseInt(output, 16)).toString(16);
    return output;
  }
}

Should work fine for hexadecimals with length of up to 16.

like image 144
Adam Iral Avatar answered Oct 24 '22 06:10

Adam Iral


To create two's-compliment numbers of fixed size I've created factory method:

 function createToInt(size) {
    if (size < 2) {
        throw new Error('Minimum size is 2');
    }
    else if (size > 64) {
        throw new Error('Maximum size is 64');
    }

    // Determine value range
    const maxValue = (1 << (size - 1)) - 1;
    const minValue = -maxValue - 1;

    return (value) => {
        if (value > maxValue || value < minValue) {
            throw new Error(`Int${size} overflow`);
        }

        if (value < 0) {
            return (1 << size) + value;
        }
        else {
            return value;
        }
    };
}

Now, to solve your question you can create functions toInt8, toInt16, toInt32, etc. And use it to convert JS numbers to two's compliment. Example with int8:

const toInt8 = createToInt(8);

'0x' + toInt8(-128).toString(16); // -> 0x80
'0x' + toInt8(127).toString(16); // -> 0x7f
'0x' + toInt8(-1).toString(16); // -> 0xff

// Values less then 16 should be padded
'0x' + toInt8(10).toString(16).padStart(2, '0); // -> 0x0a
like image 30
Paul Rumkin Avatar answered Oct 24 '22 07:10

Paul Rumkin