You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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时:

  1. digit_mask = 3 * 0x1111111111111111ULL = 0x3333333333333333
  2. diff = 0x42513 - 0x3333333333333333(无符号减法),低20位为0xF1E0,其中数位2和1对应的4位组最高位为1
  3. less_mask提取这些高位,得到0x8080(低16位)
  4. ge_mask取反后得到0x80808(对应数位4、5、3的高位)
  5. subtract_mask = 0x80808 >> 3 = 0x10101
  6. 最终结果:0x42513 - 0x10101 = 0x32412,完全符合预期!

注意事项

  • 该方法仅适用于d ≤ 15(十六进制数位最大为F),且原数的每个数位都是1~n中的值(符合题目给定条件)。
  • 所有操作都是无符号整数运算和位操作,没有循环,完全满足你的需求。

内容的提问来源于stack exchange,提问作者asdasdqwer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:50:36