将位的值反转为数字

Invert a value of bit in digit

我想反转位的数字值。

该方法应按位数反转值,如下所示:

public static void main(String[] args) {

    int res = flipBit(7,1);
}

public static int flipBit(int value, int bitIndex) {

    String bin = Integer.toBinaryString(value);
    char newChar = (char) (bin.charAt(bitIndex) ^ bin.charAt(bitIndex));
    
    //pseudo code
    bin[bitIndex] = newChar;    
    
    return Integer.parseInt(bin);
}

怎么样:

String bin = Integer.toBinaryString( value );
char newChar = (char) (bin.charAt(bitIndex) ^ bin.charAt(bitIndex));

StringBuilder sb = new StringBuilder( bin );
sb.setCharAt( bitIndex, newChar );
return sb.toString();

混合按位运算和字符串不会提高性能并降低代码的可重复性。

假设 bitIndex 是 zero-based,可以使用像这样的 XOR 运算符来完成(归功于 @Iłya Bursov,因为他已经指出了这一点在评论的前面):

public static int flipBit(int value, int bitIndex) {
    if (bitIndex < 0 || bitIndex > 31) {
        throw new IllegalArgumentException();
    }
    
    return value ^ 1 << bitIndex;
}

Online Demo

快速回顾 XOR 的工作原理。

1 ^ 1  =>  0
0 ^ 1  =>  1
1 ^ 0  =>  1
0 ^ 0  =>  0

这意味着 bit-mask 1 << bitIndex 中的零 0,通过将 1 的值按​​给定索引移动而创建,不会对结果产生影响,而应用异或。

只有掩码单个有效位会与交互:如果它会遇到1,这个位会变成0,或者如果在同一个位置有0,它会变成1

示例:

value = 7index = 2

111   -   value
 ^
100   -   bit-mask `1 << bitIndex`

011   -   result is `3`

value = 0index = 0

000   -   value
 ^
001   -   bit-mask `1 << bitIndex`

001   -   result is `1`

本方案参考:

I have string of binary in bin like "111" = 7. I need to change a bit in position bitIndex.

目前bitIndex是zero-based,从字符串的前面算起。 (这可能不是我们想要的,可以使用 bitIndex = binaryText.length() - 1 - bitIndex; 进行更改)

public class Main
{
    public static void main(String[] args) {
        String bin = Integer.toBinaryString(7);
        int bitIndex = 2;
        System.out.println("Original string:         " + bin);
        System.out.println("String with flipped bit: " + flipBit(bin, 2));
        try {
            System.out.println("Flipping using number:   " + flipBitViaNumber(bin, 2));    
        } catch (NumberFormatException ex) {
            System.err.println("Oops! Not a number: " + bin);
        }
        System.out.println("Flipping via char array: " + flipBitViaCharArray(bin, 2));
    }
    
    public static String flipBit(String binaryText, int bitIndex) {
        StringBuilder sb = new StringBuilder(binaryText.length());
        for (int i = 0; i < binaryText.length(); i++) {
            if (i == bitIndex) {
                 sb.append(binaryText.charAt(i) == '1' ? '0' : '1');
            } else {
                sb.append(binaryText.charAt(i));
            }
        }
        return sb.toString();
    }

    public static String flipBitViaNumber(String binaryText, int bitIndex) 
        throws  NumberFormatException {

        int value = Integer.parseInt(binaryText, 2);
        int pattern = 1 << (binaryText.length() - 1 - bitIndex);
        value = value ^ pattern;
        return Integer.toBinaryString(value);
    }
    
    public static String flipBitViaCharArray(String binaryText, int bitIndex) 
        throws  NumberFormatException {

        char[] chars = binaryText.toCharArray();
        chars[bitIndex] = chars[bitIndex] == '1' ? '0' : '1';
        return new String(chars);
    }    
}
Original string:         111
String with flipped bit: 110
Flipping using number:   110
Flipping via char array: 110

附加信息

A Java int 由 32 位组成,参见 https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html. Java uses the *two's complement 作为二进制表示。对 int 的按位操作在 Java 堆栈上处理,具有特定的字节码,这些字节码非常快,因为既不使用对象也不使用方法调用。