使用位运算优化JS对象与数字的双向转换实现
基于位运算优化固定位宽结构与数值的双向转换
原有实现通过二进制字符串拼接、切片完成Item对象和数值的转换,存在大量字符串与数字的类型转换开销,且高位为0时会因字符串缺省前导零出现解析错误。使用位运算(移位、按位与/或)可直接在数值层面完成转换,性能更高、逻辑更可靠。
位布局定义
首先明确各字段从最高位到最低位的位宽、偏移量(从0开始计数最低位):
flexType:占1bit,偏移量31flexNum:占7bit,偏移量24clearType:占1bit,偏移量23clearNum:占7bit,偏移量16weight:占16bit,偏移量0
总位宽32位,可直接用JS安全整数存储,无精度问题。
优化实现代码
interface Item { flexType: number; // 1 bit flexNum: number; // 7 bits clearType: number; // 1 bit clearNum: number; // 7 bits weight: number; // 16 bits } // 各字段位宽对应的掩码,用于过滤溢出值 const MASK_1BIT = 0b1; const MASK_7BIT = 0b1111111; const MASK_16BIT = 0xffff; const itemToNumber = (item: Item): number => { // 每个字段先掩码过滤溢出值,左移到对应位后按位或拼接 return ( ((item.flexType & MASK_1BIT) << 31) | ((item.flexNum & MASK_7BIT) << 24) | ((item.clearType & MASK_1BIT) << 23) | ((item.clearNum & MASK_7BIT) << 16) | (item.weight & MASK_16BIT) ) >>> 0; // 无符号右移0位保证结果为非负32位整数 }; const numberToItem = (number: number): Item => { // 右移到对应字段位置后,用掩码提取有效值 return { flexType: (number >>> 31) & MASK_1BIT, flexNum: (number >>> 24) & MASK_7BIT, clearType: (number >>> 23) & MASK_1BIT, clearNum: (number >>> 16) & MASK_7BIT, weight: number & MASK_16BIT }; }; // 测试用例 const numericItem = itemToNumber({ flexType: 1, flexNum: 42, clearType: 0, clearNum: 100, weight: 1002 }); const item = numberToItem(numericItem); console.log(item);
实现说明
- 编码(对象转数值)时,先对每个字段值做按位与操作,过滤掉超过指定位宽的溢出值,避免非法值污染相邻字段;再将每个值左移到预设的偏移位置,最后通过按位或把所有位段拼接成完整数值。
- 解码(数值转对象)时,将整数值无符号右移到对应字段的起始位置,再通过对应位宽的掩码做按位与,直接提取出目标字段的值。
- 代码中
>>> 0是为了将32位有符号整数转为无符号整数,避免最高位为1时JS把数值识别为负数的问题。 - 相比原字符串实现,位运算方案不存在前导零缺失导致的解析错位问题,鲁棒性更强。
内容的提问来源于stack exchange,提问作者hornta
相关产品推荐
相关产品推荐

