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

Java中64位Long位操作问题求助(不使用Bitset)

解决Java中Long类型位操作的符号位问题

你猜的完全没错!这个异常就是Java中有符号长整型的符号位扩展导致的。咱们来一步步拆解问题,再给出高效的解决方案:

问题根源

Java里的long是64位有符号整数,但你代码里的1 << index是用32位有符号的int来计算的——因为字面量1默认是int类型。当你操作第31位时,1 << 31会让32位int的符号位被置1,变成负数;当这个值自动转成long时,Java会做符号扩展,把高位的32位全部补成1,这就导致你后续的位操作结果带上了一堆多余的1,最终打印出来就异常了。

高效修复方案

只需要把移位操作的基准值改成long类型的1L,确保所有位操作都在64位无符号语境下进行,同时优化打印方法避免补码干扰:

1. 修正位操作方法

// 翻转指定位置的位
static final long toggle_bit(long number, int index) {
    return number ^ (1L << index);
}

// 置位指定位置
static final long set_bit(long number, int index) {
    return number | (1L << index);
}

// 复位指定位置
static final long unset_bit(long number, int index) {
    return number & ~(1L << index);
}

这里把1换成1L后,移位操作就会在64位long的范围内执行,不会触发32位int的符号位问题,不管操作0~63位中的哪一位都能正常工作。

2. 优化二进制打印方法

原来的Long.toBinaryString()会输出负数的补码形式,导致前面全是1。改用Long.toUnsignedString()可以强制按无符号64位格式输出,再补前导零即可:

static final void print_bits(long number) {
    String binary = Long.toUnsignedString(number, 2);
    // 生成64个0的字符串,用来补前导零
    String padding = "0".repeat(64);
    // 拼接成完整的64位二进制字符串
    String fullBinary = padding.substring(binary.length()) + binary;
    System.out.println(fullBinary);
}

额外建议

可以给位操作方法加上参数校验,避免传入超出0~63范围的index(Java的移位操作会对位数取模64,比如index=64等价于0位,可能不符合你的预期):

if (index < 0 || index >= 64) {
    throw new IllegalArgumentException("Index must be between 0 and 63");
}

现在再调用set_bit(0L, 31),打印出来的就是正常的64位二进制字符串啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:59:17