Java-2s补码和翻转位中的位操作

Java-2s补码和翻转位中的位操作,java,bit-manipulation,Java,Bit Manipulation,我最近在研究Java中but操作的一些问题,我提出了两个问题 1) 首先,我想到了在一个数字中翻转所有位的问题 我找到了这个解决方案: public class Solution { public int flipAllBits(int num) { int mask = (1 << (int)Math.floor(Math.log(num)/Math.log(2))+1) - 1; return num ^ mask; } } 公共

我最近在研究Java中but操作的一些问题,我提出了两个问题

1) 首先,我想到了在一个数字中翻转所有位的问题

我找到了这个解决方案:

public class Solution {
    public int flipAllBits(int num) {
        int mask = (1 << (int)Math.floor(Math.log(num)/Math.log(2))+1) - 1;
        return num ^ mask;
    }
}
公共类解决方案{
公共int flipAllBits(int num){
int mask=(11)不需要调用数学对象。在Java(或C)中翻转任何顺序类型中的所有位不是算术运算。它是按位运算。使用“^”运算符,仅使用1-作为操作数,无论C/C++中int的大小如何,或使用序数类型作为参数T的Java模板。波浪号“~”运算符是另一个选项

T i = 0xf0f0f0f0;
System.out.println(T.toHexString(i));
i ^= -1;
System.out.println(T.toHexString(i));
i = ~ i;
System.out.println(T.toHexString(i));

2) 由于整数的整个范围映射到2的互补变换中的整数的整个范围,因此不可能检测一个数字是否为2的补码,除非知道计算2的补码的数字范围以及两个集合(之前和之后)是互斥的。

掩码计算是相当不可理解的,我想它(尝试,因为你提到它是错误的)使掩码达到并包括最高设置位。这是否对“翻转所有位”有用是另一个可能的讨论点,因为至少对我来说,“所有位”是指全部32个,而不是一些取决于值的数字。但如果这是你想要的,那么这就是你想要的。特别是结合第二个问题,这对我来说似乎是个错误,所以你从一开始就实施了错误的事情-见底部

无论如何,可以使用一些相当不错的bitmath生成掩码,这不会对可能的边缘情况产生任何怀疑(例如
Math.log(0)
可能不好,k=32对应于负数,也可能不好放入日志中):

请注意,此函数具有奇数属性,它几乎总是返回一个比输入值低的无符号数字,除了0。它翻转位,因此名称并非完全错误,而是
flipAllBits(flipAllBits(x))!=x
(通常),而名称表明它应该是一个对合

至于第二个问题,没有什么可确定的。二的补码是一种可以解释位向量的方案——任何位向量。因此,这实际上是一种选择;以这种方式或其他方式解释给定的位向量。在Java中,“默认”解释是二的补码(例如toString将根据int的两个补码含义来解释它来打印int),但您不必使用它,您可以(小心地)将
int
视为无符号,或视为布尔数组,或将几个位字段打包在一起,等等

如果您想反转所有位,但犯了一个常见错误,即假定int中的位数是可变的(因此需要计算一个覆盖“所有位”的掩码),我有一些好消息要告诉您,因为反转所有位要容易得多:


如果您正在阅读“反转所有位”在2的补码上下文中,它将具有上述含义,因此所有位,包括最高设定位的左边的位。

该位的可能重复不会直接回答这两个问题中的任何一个,但这两个问题可能应该是单独的问题,并且可能需要澄清。作为旁注,要翻转所有位,您只需使用
~
运算符。您没有理解第二个问题的含义。感兴趣的是检测一个位序列是否为2的补码(Java int)形式(Java unsigned int),如果没有额外的信息,这一点是不可能的。@Fauchristan我没有错过它,我专门写了一段,告诉你,不仅你不能检测到它,而且没有什么可以检测的。
int m = num | (num >> 16);
m |= m >> 8;
m |= m >> 4;
m |= m >> 2;
m |= m >> 1;
return num ^ m;
return ~num;