15

例如,我有一个以十六进制数字形式给出的有符号值,0xffeb并希望将其转换-21为“普通”Javascript 整数。

到目前为止,我已经编写了一些代码:

function toBinary(a) { //: String
    var r = '';
    var binCounter = 0;
    while (a > 0) {
        r = a%2 + r;
        a = Math.floor(a/2);
    }
    return r;
}

function twoscompl(a) { //: int
    var l = toBinaryFill(a).length;
    var msb = a >>> (l-1);

    if (msb == 0) {
        return a;
    }

    a = a-1;
    var str = toBinary(a);
    var nstr = '';
    for (var i = 0; i < str.length; i++) {
        nstr += str.charAt(i) == '1' ? '0' : '1';
    }
    return (-1)*parseInt(nstr);
}

问题是,我的函数返回 1 作为两个数字的 MSB,因为仅在二进制表示“字符串”的 MSB 处查看。对于这种情况,两个数字都是 1:

-21 => 0xffeb => 1111 1111 1110 1011
 21 => 0x15   =>              1 0101

你有什么想法来实现这个更有效和更好的吗?

问候,神话

4

5 回答 5

25

用于parseInt()转换(只接受您的十六进制字符串):

parseInt(a);

然后使用掩码来确定是否设置了 MSB:

a & 0x8000

如果返回一个非零值,你就知道它是负数。

总结一下:

a = "0xffeb";
a = parseInt(a, 16);
if ((a & 0x8000) > 0) {
   a = a - 0x10000;
}

请注意,这仅适用于 16 位整数(short在 C 中)。如果您有 32 位整数,则需要不同的掩码和减法。

于 2012-11-20T07:42:37.680 回答
17

我想出了这个

function hexToInt(hex) {
    if (hex.length % 2 != 0) {
        hex = "0" + hex;
    }
    var num = parseInt(hex, 16);
    var maxVal = Math.pow(2, hex.length / 2 * 8);
    if (num > maxVal / 2 - 1) {
        num = num - maxVal
    }
    return num;
}

和用法:

var res = hexToInt("FF"); // -1
res = hexToInt("A"); // same as "0A", 10
res = hexToInt("FFF"); // same as "0FFF", 4095
res = hexToInt("FFFF"); // -1

所以基本上十六进制转换范围取决于十六进制的长度,这就是我想要的。希望能帮助到你。

于 2016-01-08T14:22:05.007 回答
5

基于@Bart Friederichs,我附带了:

function HexToSignedInt(num, numSize) {
    var val = {
        mask: 0x8 * Math.pow(16, numSize-1), //  0x8000 if numSize = 4
        sub: -0x1 * Math.pow(16, numSize)    //-0x10000 if numSize = 4
    }
    if((parseInt(num, 16) & val.mask) > 0) { //negative
        return (val.sub + parseInt(num, 16))
    }else {                                 //positive
        return (parseInt(num,16))
    }
 }

所以现在您可以指定确切的长度(以半字节为单位)。

var numberToConvert = "CB8";
HexToSignedInt(numberToConvert, 3);
//expected output: -840
于 2018-11-22T19:15:22.400 回答
2
function hexToSignedInt(hex) {
    if (hex.length % 2 != 0) {
        hex = "0" + hex;
    }
    var num = parseInt(hex, 16);
    var maxVal = Math.pow(2, hex.length / 2 * 8);
    if (num > maxVal / 2 - 1) {
        num = num - maxVal
    }
    return num;
}

function hexToUnsignedInt(hex){
    return parseInt(hex,16);
}

第一个用于有符号整数,第二个用于无符号整数

于 2018-03-21T10:57:32.787 回答
0

由于我必须将绝对数值转换为范围从 -2^24 到 2^24-1 的 int32 值,因此我想出了这个解决方案,您只需将输入更改为一个数字parseInt(hex, 16),在您的情况下,nBytes 是2.

function toSignedInt(value, nBytes) { // 0 <= value < 2^nbytes*4, nBytes >= 1, 
  var hexMask = '0x80' + '00'.repeat(nBytes - 1);
  var intMask = parseInt(hexMask, 16);
  if (value >= intMask) {
    value = value - intMask * 2;
  }
  return value;
}

var vals = [       // expected output
  '0x00',          // 0
  '0xFF',          // 255
  '0xFFFFFF',      // 2^24 - 1 = 16777215
  '0x7FFFFFFF',    // 2^31 -1 = 2147483647
  '0x80000000',    // -2^31 = -2147483648
  '0x80000001',    // -2^31 + 1 = -2147483647
  '0xFFFFFFFF',    // -1
];
for (var hex of vals) {
  var num = parseInt(hex, 16);
  var result = toSignedInt(num, 4);
  console.log(hex, num, result);
}

var sampleInput = '0xffeb';
var sampleResult = toSignedInt(parseInt(sampleInput, 16), 2);
console.log(sampleInput, sampleResult); // "0xffeb", -21
于 2021-05-14T08:06:45.387 回答