Преобразование десятичного числа со знаком в шестнадцатеричное, закодированное с помощью дополнения two

#javascript #twos-complement

#javascript #двойки-дополнение

Вопрос:

Мне нужно кодировать подпись целое число в шестнадцатеричном виде, используя по два дополнения нотации. Например, я хотел бы преобразовать

 e.g. -24375 to 0xffffa0c9.
  

До сих пор я работал над следующими строками:

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

Это соответствует тому, что отображает Wolfram Alpha, но я не уверен, как перейти к 24-битному int-представлению числа со знаком (ffffa0c9).

Я разработал, как взять двоичное число без знака и представить его как дополнение two:

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

но я не уверен, что нужно преобразовать двоичное представление этого числа в шестнадцатеричное.

Есть идеи?

Ответ №1:

Вот довольно простое решение, использующее 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;
  }
}
  

Должно нормально работать для шестнадцатеричных чисел длиной до 16.

Комментарии:

1. это работает идеально

Ответ №2:

Чтобы создать числа с дополнением two фиксированного размера, я создал 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;
        }
    };
}
  

Теперь, чтобы решить ваш вопрос, вы можете создавать функции toInt8 , toInt16 , toInt32 и т.д. И используйте это для преобразования чисел JS в дополнение two. Пример с 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