JS——十六进制数转十进制(带符号)

原文地址

Javascript 16进制转有符号的10进制整数

前言

今天做小程序开发,需要将对应蓝牙特征值中的数据(十六进制字符串)转化为十进制数。

var a = "F831";
console.log("####->"+parseInt(a,16));

发现0xF831转换为十进制后,结果却是63537。但在底层开发中,数据类型为int16_t(有符号 2字节)。转换的完全对不上呀!

正文

朋友推荐一篇参考博客。下面为转载内容。

这里我们就需要温习一下数据在底层的转换,我们都知道数据在计算机里都是用二进制形式存储的。有符号的整数有两种方式存储,一种正数存储,一种负数存储。正数存储就是以真二进制的方式,最高位为0,后面每一位都表示2的幂次。而负数则麻烦的多,它采用二进制补码的形式存储。确定一个负数的二进制需要三步:

  • 1、确定该数字的绝对值的二进制,因为是负数所以最高位的“0”改为“1”,其为原码。
  • 2、将该绝对值,除了最高位的符号位外其他位的“0”替换成“1”,“1”替换成“0”,这就是二进制的反码。
  • 3、反码加上1,确定其补码。

比如-256转换为二进制,具体步骤如下:

  • 1.先将256转换为二进制数为1 0000 0000,因位数不是8的倍数,需要在不足的高位补上0,得0000 0001 0000 0000。因为-256是负数,所以最高位改为1000 0001 0000 0000。
  • 2.再将除了符号位其他位的1和0对换,得1111 1110 1111 1111。
  • 3.把反码加上1得1111 1111 0000 0000。

现在再把它转为16进制,就得到上面我们一开始的“FF00”了。

ps:看到一个关于负数为什么是用补码存储的有趣说法,说计算机喜欢加法,正数的二进制和负数的二进制相加得0,这样极大减少了内存占用。

具体分析

首先先定义一个变量:

var i = "F831";

JavaScript只提供了2-32进制转换为10的函数,和10进制转换为2-32的方法,所以我们要把一个16进制转换为2进制需要使用其10进制作为中间量。

let two = parseInt(i, 16).toString(2);

再求出变量应有的位数,在不足的位数上补“0”。

let bitNum=i.length*4;
if (two.length < bitNum) {
  while (two.length < bitNum) {
    two = "0" + two;
  }
}

判断它的最高位是否是0,如果是,转换为10进制后原样输出。

if (two.substring(0, 1) == "0") {
  two = parseInt(two, 2);
}

如果不是,按照之前提供的步骤处理一下。

else {
	let two_unsign = "";
	two = parseInt(two, 2) - 1;//减一
	two = two.toString(2);
	two_unsign = two.substring(1, bitNum);//截取除了最高位以外的位
	two_unsign = two_unsign.replace(/0/g, "z");//反码
	two_unsign = two_unsign.replace(/1/g, "0");
	two_unsign = two_unsign.replace(/z/g, "1");
	two = parseInt(-two_unsign, 2);//补上负号
}

我们封装一下。

module.exports=(i)=>{
  let two = parseInt(i, 16).toString(2);
  let bitNum=i.length*4;
  if (two.length < bitNum) {
    while (two.length < bitNum) {
      two = "0" + two;
    }
  }
 
  if (two.substring(0, 1) == "0") {
    two = parseInt(two, 2);
 
    return two;
  } else {
    let two_unsign = "";
    two = parseInt(two, 2) - 1;
    two = two.toString(2);
    two_unsign = two.substring(1, bitNum);
    two_unsign = two_unsign.replace(/0/g, "z");
    two_unsign = two_unsign.replace(/1/g, "0");
    two_unsign = two_unsign.replace(/z/g, "1");
    two = parseInt(-two_unsign, 2);
 
    return two;
  }
}

js定义funtion

function hex2int(hexStr) {
  let twoStr = parseInt(hexStr,16).toString(2); // 将十六转十进制,再转2进制
  let bitNum = hexStr.length * 4; // 1个字节 = 8bit ,0xff 一个 "f"就是4位
  if(twoStr.length < bitNum){
    while(twoStr.length < bitNum){
      twoStr = "0" + twoStr;
    }
  }
  if(twoStr.substring(0,1) == "0"){
    // 正数
    twoStr = parseInt(twoStr,2); // 二进制转十进制
    return twoStr;
  }else{
    // 负数
    let twoStr_unsign = "";

    console.log("hex2int--->"+parseInt(twoStr,2));
    twoStr = parseInt(twoStr,2) - 1; // 补码:(负数)反码+1,符号位不变;相对十进制来说也是 +1,但这里是负数,+1就是绝对值数据-1
    console.log("hex2int--->"+twoStr);

    twoStr = twoStr.toString(2);
    twoStr_unsign = twoStr.substring(1,bitNum); // 舍弃首位(符号位)
    // 去除首字符,将0转为1,将1转为0   反码
    twoStr_unsign = twoStr_unsign.replace(/0/g, "z");
    twoStr_unsign = twoStr_unsign.replace(/1/g, "0");
    twoStr_unsign = twoStr_unsign.replace(/z/g, "1");
    
    console.log("hex2int--->"+twoStr_unsign);
    console.log("hex2int--->"+(-twoStr_unsign));
    twoStr = parseInt(-twoStr_unsign, 2);
    return twoStr;
  }
}

测试

var a = "F831";
console.log("####->"+hex2int(a));

在这里插入图片描述

<think>好的,我现在需要在HTML5中将十六进制换为short类型。首先,我需要明确用户的需求。用户提到的H5可能是指HTML5,而他们希望将十六进制换为short类型,通常是指16位有符号整。在JavaScript中,处理这种换需要注意据类型和可能的溢出问题。 首先,我需要回忆JavaScript中的据类型。JS中没有显式的short类型,但可以通过其他方式模拟。十六进制值在JS中通常以字符串形式存在,比如"0xFF"。要将这样的字符串换为字,可以使用parseInt,并指定基16。例如,parseInt("FF", 16)会得到255。但是,short是有符号的16位整,范围是-32768到32767。因此,如果换后的值超过32767,就需要考虑溢出,将其换为负。 比如,假设用户有一个十六进制字符串"0xFFFE",使用parseInt换后得到65534。但作为16位有符号,这实际上是-2。这时,如何将65534换为-2呢?可能需要使用位运算符,例如使用按位非操作符或者通过减去65536(即2^16)来处理。或者更简单的方法是将结果视为有符号,通过判断最高位是否为1来确定符号。 另外,可能还需要处理字节序的问题,特别是当处理多字节据时。但用户的问题可能只需要单个16位的换。例如,将两个字节的十六进制字符串换为short。比如,如果字符串是"FFFE",那么换为十进制就是65534,再为有符号的short,就是-2。这可以通过以下步骤实现:将字符串为整,然后检查是否超过32767,如果超过,则减去65536得到负。 现在,我需要验证这些步骤是否正确。例如,测试几个例子:比如"0x8000"对应的十进制是32768,作为有符号的short应该是-32768。使用parseInt("8000", 16)得到32768,然后减去65536得到-32768。另一个例子,"0x7FFF"对应32767,是最大的正。而"0xFFFF"对应65535,减去65536得到-1,正确。 因此,换的关键在于将解析后的换为16位有符号整。JavaScript中可以使用DataView来处理,或者通过位运算。例如,使用Int16Array,将值放入组中,然后读取第一个元素。或者更简单的方式是按上述方法进行值调整。 总结步骤:1. 去除十六进制字符串的前缀(如0x)。2. 使用parseInt换为十进制。3. 检查该是否大于等于0x8000(即32768),如果是,则减去65536得到负,否则直接使用。或者使用位运算符,例如使用按位左移和右移来获得有符号。例如,将值与0xFFFF进行按位与操作,然后使用右移符号位填充。 另外,考虑用户提供的引用中,引用[4]提到浮点和整型的换使用了指针的方式,这在JS中不适用,但可能提示了类型换的思路。例如,在JS中可以使用TypedArray来模拟类似的内存操作。比如,将值写入ArrayBuffer,然后以不同的类型读取。 例如,创建一个ArrayBuffer,使用Uint16Array写入解析后的值,再用Int16Array读取同一缓冲区,这样会自动换为有符号的short。这种方法更可靠,因为直接利用JS的类型化组处理字节级别的换,避免手动计算溢出。 具体步骤可能如下: 1. 去除十六进制字符串的前缀(如"0x"或"#")。 2. 使用parseInt(str, 16)得到无符号整。 3. 创建一个ArrayBuffer,长度为2字节。 4. 使用Uint16Array将值写入缓冲区。 5. 使用Int16Array读取同一缓冲区,得到有符号的short。 例如: ```javascript function hexToShort(hexStr) { // 去除可能的0x前缀 hexStr = hexStr.replace(/^0x/, ''); // 解析为无符号整 let num = parseInt(hexStr, 16); // 创建缓冲区 let buffer = new ArrayBuffer(2); let uint16View = new Uint16Array(buffer); let int16View = new Int16Array(buffer); uint16View[0] = num; return int16View[0]; } ``` 这样,当输入"FFFE"时,parseInt得到65534,写入Uint16Array后,用Int16Array读取就会得到-2。这方法更准确,因为直接利用类型化组的处理方式,无需手动计算。 此外,需要注意输入是否有效,例如长度是否为4个字符(两个字节),否则需要处理截断或填充。例如,如果输入的十六进制字符串长度为3,可能需要前面补零,或者截断高位字节。但用户可能需要根据具体情况处理,比如确保输入是4位的十六进制字符串,代表两个字节。 因此,完整的解决方案应包括输入验证和处理,以确保换正确。比如,检查输入是否为有效的十六进制字符串,并确保其长度合适。 总结,用户的问题可以通过使用类型化组(如Uint16Array和Int16Array)来高效且准确地实现十六进制到short类型的换。同时,需要处理输入的格式和有效性。</think>在HTML5(JavaScript)中,将十六进制换为`short`类型(16位有符号整)可通过以下步骤实现: --- ### 步骤说明 1. **去除前缀**:若十六进制字符串包含`0x`或`#`前缀,需先移除。 2. **解析为无符号整**:使用`parseInt(hexStr, 16)`将字符串换为十进制。 3. **处理溢出**:若值超过`0x7FFF`(即32767),需换为负(通过类型化组自动处理符号位)。 --- ### 代码实现 ```javascript function hexToShort(hexStr) { // 1. 移除前缀(如0x或#) hexStr = hexStr.replace(/^0x|#/g, ''); // 2. 解析为无符号整 const num = parseInt(hexStr, 16); // 3. 使用类型化组处理溢出和符号位 const buffer = new ArrayBuffer(2); new DataView(buffer).setUint16(0, num, false); // 大端序写入无符号 return new DataView(buffer).getInt16(0, false); // 读取为有符号short } // 示例 console.log(hexToShort("FFFE")); // 输出: -2 console.log(hexToShort("7FFF")); // 输出: 32767 console.log(hexToShort("8000")); // 输出: -32768 ``` --- ### 原理解释 - **类型化组**:通过`DataView`将值写入缓冲区,确保按16位无符号整存储,再以有符号`short`读取,自动完成符号扩展[^4]。 - **字节序控制**:`setUint16`和`getInt16`的第三个参为字节序(`false`表示大端序),需根据输入据格式调整。 --- ### 输入验证(可选) ```javascript function validateHex(hexStr) { return /^(0x|#)?[0-9a-fA-F]{1,4}$/.test(hexStr); } if (!validateHex("FFFE")) { throw new Error("无效的十六进制格式"); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值