C++中仅用位操作实现十六进制指定数位减1的方案问询
解决方案:纯位操作实现十六进制数位减1
当然可以做到!核心思路是先通过位操作生成一个减法掩码,这个掩码在所有原数位≥d的位置上是0x1(对应十六进制的一个数位位),其余位置是0,最后用原数减去这个掩码即可得到结果。
具体步骤
- 构造数位对比掩码:生成一个每个4位组都等于
d的uint64_t数,比如d=3时就是0x3333333333333333。可以用d * 0x1111111111111111ULL快速生成,因为0x1111111111111111是十六进制中16个连续的1(每个占4位),乘以d后自然每个4位组都是d。 - 定位需要减1的数位:用原数减去这个对比掩码,利用无符号减法的特性:
- 如果原数位
x ≥ d,则x - d的4位组最高位是0; - 如果
x < d,无符号减法会产生借位,结果的4位组最高位是1。
- 如果原数位
- 生成减法掩码:提取出所有最高位为0的位置(即
x ≥ d的数位),将这些位置转换为对应十六进制数位的0x1标记,组合成最终的减法掩码。 - 计算结果:原数减去减法掩码,得到每个≥d的数位减1后的结果。
代码实现
#include <cstdint> uint64_t adjust_hex_digits(uint64_t hex, uint8_t d) { // 构造每个4位组都是d的掩码 const uint64_t digit_mask = d * 0x1111111111111111ULL; // 计算原数与digit_mask的差 const uint64_t diff = hex - digit_mask; // 提取所有x < d的数位的最高位(每个4位组的第3位) const uint64_t less_mask = diff & 0x8888888888888888ULL; // 取反得到x ≥ d的数位的最高位掩码 const uint64_t ge_mask = ~less_mask & 0x8888888888888888ULL; // 将最高位掩码右移3位,转换为每个数位的0x1标记 const uint64_t subtract_mask = ge_mask >> 3; // 原数减去掩码得到结果 return hex - subtract_mask; }
验证你的例子
当hex=0x42513,d=3时:
digit_mask = 3 * 0x1111111111111111ULL = 0x3333333333333333diff = 0x42513 - 0x3333333333333333(无符号减法),低20位为0xF1E0,其中数位2和1对应的4位组最高位为1less_mask提取这些高位,得到0x8080(低16位)ge_mask取反后得到0x80808(对应数位4、5、3的高位)subtract_mask = 0x80808 >> 3 = 0x10101- 最终结果:
0x42513 - 0x10101 = 0x32412,完全符合预期!
注意事项
- 该方法仅适用于
d ≤ 15(十六进制数位最大为F),且原数的每个数位都是1~n中的值(符合题目给定条件)。 - 所有操作都是无符号整数运算和位操作,没有循环,完全满足你的需求。
内容的提问来源于stack exchange,提问作者asdasdqwer
相关产品推荐
相关产品推荐

