原生JS实现十进制与有符号2's complement互转及数制转换问题
2补码(2's complement)原理讲解与数制转换实现方案
2补码核心原理
2补码是计算机领域用于表示有符号整数的通用编码规则,核心优势是可以将减法运算直接转换为加法运算,无需额外处理符号位逻辑,具体规则如下:
- 固定位宽的二进制数最高位为符号位:
0代表正数,1代表负数 - 正数的2补码与它的原码完全一致
- 负数的2补码计算规则:先取对应正数的原码,按位取反得到反码,再加1后保留指定位宽的有效位即可
- 2补码转十进制规则:若最高位为1,最终十进制值 = 二进制串对应的无符号十进制值 - 2的位宽次方;若最高位为0,直接取无符号十进制值即可
举个实际计算例子:计算8位2补码下的-5
- 正数
5的8位原码为00000101 - 按位取反得到反码
11111010 - 加1后得到
11111011,即为-5的8位2补码 - 反向验证:
11111011的无符号十进制值为251,251 - 2^8 = 251 - 256 = -5,结果正确
适配现有代码的实现方案
和你参考站点的功能一致,需要支持自定义位宽(常用可选8/16/32/64位,默认设置为32位即可),以下是可直接整合进你现有代码的新增函数,以及原有函数的改造方案:
新增2补码专用工具函数
/** * 二进制字符串转2补码十进制值 * @param {string} binary 二进制字符串 * @param {number} bitWidth 位宽,默认32位 * @returns {number} 2补码对应的十进制值 */ export function binary2DecimalTwosComplement(binary, bitWidth = 32) { // 补前导0到指定位宽,超出位宽的部分截断高位 const paddedBinary = binary.padStart(bitWidth, '0').slice(-bitWidth); const unsignedVal = parseInt(paddedBinary, 2); // 最高位为1代表负数 if (paddedBinary[0] === '1') { return unsignedVal - Math.pow(2, bitWidth); } return unsignedVal; } /** * 十进制数转2补码二进制字符串 * @param {number} decimal 十进制整数 * @param {number} bitWidth 位宽,默认32位 * @returns {string} 2补码二进制字符串 */ export function decimal2BinaryTwosComplement(decimal, bitWidth = 32) { const maxPositive = Math.pow(2, bitWidth - 1) - 1; const minNegative = -Math.pow(2, bitWidth - 1); // 校验数值是否在当前位宽的合法范围内 if (decimal > maxPositive || decimal < minNegative) { throw new Error(`数值超出${bitWidth}位2补码支持范围:${minNegative} ~ ${maxPositive}`); } // 正数直接补前导0即可 if (decimal >= 0) { return decimal.toString(2).padStart(bitWidth, '0'); } // 负数处理:取对应正数的二进制,按位取反后加1 const positiveBinary = (-decimal).toString(2).padStart(bitWidth, '0'); const inverted = positiveBinary.split('').map(bit => bit === '0' ? '1' : '0').join(''); return (parseInt(inverted, 2) + 1).toString(2).padStart(bitWidth, '0'); } /** * 十六进制转2补码十进制值 * @param {string} hex 十六进制字符串 * @param {number} bitWidth 位宽,默认32位 * @returns {number} 2补码十进制值 */ export function hex2DecimalTwosComplement(hex, bitWidth = 32) { const binary = parseInt(hex, 16).toString(2).padStart(bitWidth, '0').slice(-bitWidth); return binary2DecimalTwosComplement(binary, bitWidth); } /** * 十进制转2补码十六进制字符串 * @param {number} decimal 十进制整数 * @param {number} bitWidth 位宽,默认32位 * @returns {string} 2补码十六进制字符串 */ export function decimal2HexTwosComplement(decimal, bitWidth = 32) { const binary = decimal2BinaryTwosComplement(decimal, bitWidth); return parseInt(binary, 2).toString(16).toUpperCase(); }
原有函数改造示例
可以在现有转换函数中新增开关参数,控制是否返回2补码结果,以fromHex函数为例:
export function fromHex(hex, enableTwosComplement = false, bitWidth = 32) { let resp = new Object(); resp.binary = hex2Binary(hex); resp.decimal = hex2Decimal(hex); // 开启2补码时追加对应结果 if (enableTwosComplement) { resp.decimalTwosComplement = hex2DecimalTwosComplement(hex, bitWidth); resp.binaryTwosComplement = parseInt(hex, 16).toString(2).padStart(bitWidth, '0').slice(-bitWidth); } return resp; }
其余fromDecimal、fromBinary函数均可按照相同逻辑改造,新增开关和位宽参数即可实现和参考站点完全一致的功能。
内容的提问来源于stack exchange,提问作者user12818329
相关产品推荐
相关产品推荐

