Javascript:将(十六进制)有符号整数转换为 javascript 值

Posted

技术标签:

【中文标题】Javascript:将(十六进制)有符号整数转换为 javascript 值【英文标题】:Javascript: convert a (hex) signed integer to a javascript value 【发布时间】:2012-11-08 05:47:05 【问题描述】:

我有一个以十六进制数形式给出的有符号值,例如 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

您有什么想法可以更高效、更好地实现这一点吗?

您好, 神话

【问题讨论】:

【参考方案1】:

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

parseInt(a);

然后使用掩码来判断是否设置了 MSB:

a & 0x8000

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

总结一下:

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

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

【讨论】:

不确定它有多重要,但由于您使用的是十六进制和parseInt,您可能想要使用parseInt(a, 16) @Ian,我在 Firebug 控制台中对其进行了测试,parseInt("0xffeb") 解析正确。当省略0x 时,它需要基数。为了安全起见,应始终添加它。我更新了我的答案。 确实可以不用它,但是parseInt 在没有它的情况下也可以处理普通的 int 字符串...除非您不小心输入了错误的输入(例如期望基数 10 解析但出于任何原因提供“012” ) 并获得10。这似乎也是浏览器一致性的事情。我刚刚发现始终提供基数会更好,即使您正在使用“正常”以 10 为基数。只是想指出这一切:) 惊人的简洁代码!世界可以如此简单...... :-) 工作愉快...谢谢!【参考方案2】:

我想出了这个

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

所以基本上十六进制转换范围取决于十六进制的长度,这就是我要找的。希望对您有所帮助。

【讨论】:

【参考方案3】:

基于@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

【讨论】:

我真的很喜欢这个解决方案。我必须在否定检查中添加一个额外的括号才能让我的所有测试通过。例如。 HexToSignedInt("7d",2) if((parseInt(num, 16) & val.mask) > 0) //negative 这个解决方案总体上很好,但是对于应该导致最小负值的值失败:(0x80, 2) 应该给出 -128,而不是 128,输入 2 的范围是从 0x00 到 0xFF应该从-128到127,其中0x00-7F是0-127,0x80-0xFF从-128到-1【参考方案4】:
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);

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

【讨论】:

【参考方案5】:

由于我必须将绝对数值转换为 int32 值,范围从 -2^24 到 2^24-1, 我想出了这个解决方案,您只需通过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

【讨论】:

以上是关于Javascript:将(十六进制)有符号整数转换为 javascript 值的主要内容,如果未能解决你的问题,请参考以下文章

asp 如何将中文转成无符号十进制整数(50分)

Python 格式化输出print

c ++流负数转换

C#Winform基础 十进制(整数)转换为十六进制有符号

使用 Javascript 将十进制转换为十六进制或 Unicode

将十进制字符串 IP 掩码转换为带有尾随零的无符号整数