java二进制反转_java-按位运算符可以简单地翻转整数中的所有位?

java-按位运算符可以简单地翻转整数中的所有位?

我必须翻转整数的二进制表示形式中的所有位。 鉴于:

10101

输出应为

01010

与整数一起使用时,按位运算符可以完成此操作? 例如,如果我正在编写类似int flipBits(int n);的方法,那么体内会发生什么? 我只需要翻转数字中已经存在的内容,而不是翻转整数中的所有32位。

13个解决方案

62 votes

~一元运算符是按位取反。 如果您所需的位数少于int所能容纳的位数,那么您需要在事后用&对其进行屏蔽。

Ignacio Vazquez-Abrams answered 2020-07-21T22:40:08Z

25 votes

只需使用按位非运算符(1 << k) - 1。

int flipBits(int n) {

return ~n;

}

要使用k个最低有效位,请将其转换为正确的掩码。

(我假设您当然至少需要1位,这就是为什么mask从1开始的原因)

int flipBits(int n, int k) {

int mask = 1;

for (int i = 1; i < k; ++i)

mask |= mask << 1;

return ~n & mask;

}

如LưuVĩnhPhúc所建议,可以将掩码创建为(1 << k) - 1,而不是使用循环。

int flipBits2(int n, int k) {

int mask = (1 << k) - 1;

return ~n & mask;

}

George answered 2020-07-21T22:40:41Z

13 votes

有多种方法可以使用操作翻转所有位

x = ~x; // has been mentioned and the most obvious solution.

x = -x - 1; or x = -1 * (x + 1);

x ^= -1; or x = x ^ ~0;

Peter Lawrey answered 2020-07-21T22:41:01Z

4 votes

好吧,因为到目前为止,只有一种解决方案可以给出“正确的”结果,但这真的不是一个很好的解决方案(使用字符串来计数前导零吗?这会让我梦dream以求的;))

因此,这里我们提供了一个不错的干净解决方案,该解决方案应该可以工作-尽管尚未对其进行全面的测试,但是您会发现要点。 确实,不具有无符号类型的Java对于此类问题非常烦人,但它仍然应该非常高效(而且,如果我这么说,比从数字中创建字符串要优雅得多)

private static int invert(int x) {

if (x == 0) return 0; // edge case; otherwise returns -1 here

int nlz = nlz(x);

return ~x & (0xFFFFFFFF >>> nlz);

}

private static int nlz(int x) {

// Replace with whatever number leading zero algorithm you want - I can think

// of a whole list and this one here isn't that great (large immediates)

if (x < 0) return 0;

if (x == 0) return 32;

int n = 0;

if ((x & 0xFFFF0000) == 0) {

n += 16;

x <<= 16;

}

if ((x & 0xFF000000) == 0) {

n += 8;

x <<= 8;

}

if ((x & 0xF0000000) == 0) {

n += 4;

x <<= 4;

}

if ((x & 0xC0000000) == 0) {

n += 2;

x <<= 2;

}

if ((x & 0x80000000) == 0) {

n++;

}

return n;

}

Voo answered 2020-07-21T22:41:26Z

4 votes

更快,更简单的解决方案:

/* inverts all bits of n, with a binary length of the return equal to the length of n

k is the number of bits in n, eg k=(int)Math.floor(Math.log(n)/Math.log(2))+1

if n is a BigInteger : k= n.bitLength();

*/

int flipBits2(int n, int k) {

int mask = (1 << k) - 1;

return n ^ mask;

}

serge boisse answered 2020-07-21T22:41:46Z

0 votes

我必须确保看到一些示例,但是由于二进制补码运算,您可能会得到意外的值。 如果该数字具有前导零(如26),则〜运算符会将其翻转为前导零-得出负数。

一种可能的解决方法是使用Integer类:

int flipBits(int n){

String bitString = Integer.toBinaryString(n);

int i = 0;

while (bitString.charAt(i) != '1'){

i++;

}

bitString = bitString.substring(i, bitString.length());

for(i = 0; i < bitString.length(); i++){

if (bitString.charAt(i) == '0')

bitString.charAt(i) = '1';

else

bitString.charAt(i) = '0';

}

int result = 0, factor = 1;

for (int j = bitString.length()-1; j > -1; j--){

result += factor * bitString.charAt(j);

factor *= 2;

}

return result;

}

我现在没有设置Java环境来对其进行测试,但这是一般的想法。 基本上只是将数字转换为字符串,切掉前导零,翻转位,然后将其转换回数字。 Integer类甚至可以通过某种方式将字符串解析为二进制数。 我不知道这是否是解决问题的方式,这可能不是解决问题的最有效方法,但它会产生正确的结果。

编辑:polygenlubricants对这个问题的答案可能也有帮助

Ben Sutton answered 2020-07-21T22:42:20Z

0 votes

我有另一种解决这种情况的方法,

public static int complementIt(int c){

return c ^ (int)(Math.pow(2, Math.ceil(Math.log(c)/Math.log(2))) -1);

}

它使用XOR来获取补码位,要对其进行补码,我们需要将数据与1进行XOR,例如:

101 XOR 111 = 010

(111是“关键字”,它是通过搜索数据的“ n”平方根生成的)

如果使用〜(补码),则结果将取决于其变量类型,如果使用int,则它将作为32位处理。

Rio answered 2020-07-21T22:42:57Z

0 votes

由于我们只需要翻转整数所需的最小位(例如50为110010,而取反后变为001101,即13),我们可以一次将单个位从LSB转换为MSB,并保持移位 右边的位,并相应施加2的幂。下面的代码完成所需的工作:

int invertBits (int n) {

int pow2=1, int bit=0;

int newnum=0;

while(n>0) {

bit = (n & 1);

if(bit==0)

newnum+= pow2;

n=n>>1;

pow2*=2;

}

return newnum;

}

tycoon_9990 answered 2020-07-21T22:43:18Z

0 votes

import java.math.BigInteger;

import java.util.Scanner;

public class CodeRace1 {

public static void main(String[] s) {

long input;

BigInteger num,bits = new BigInteger("4294967295");

Scanner sc = new Scanner(System.in);

input = sc.nextInt();

sc.nextLine();

while (input-- > 0) {

num = new BigInteger(sc.nextLine().trim());

System.out.println(num.xor(bits));

}

}

}

user5914697 answered 2020-07-21T22:43:33Z

0 votes

来自openJDK的Integer.reverse()实现:

public static int More ...reverse(int i) {

i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;

i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;

i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;

i = (i << 24) | ((i & 0xff00) << 8) |

((i >>> 8) & 0xff00) | (i >>> 24);

return i;

}

根据我在笔记本电脑上的实验,以下实现速度更快:

public static int reverse2(int i) {

i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;

i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;

i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;

i = (i & 0x00ff00ff) << 8 | (i >>> 8) & 0x00ff00ff;

i = (i & 0x0000ffff) << 16 | (i >>> 16) & 0x0000ffff;

return i;

}

不知道其背后的原因是什么-因为它可能取决于将Java代码解释为机器代码的方式...

user3438301 answered 2020-07-21T22:44:02Z

0 votes

如果您只想翻转整数中“已使用”的位,请尝试以下操作:

public int flipBits(int n) {

int mask = (Integer.highestOneBit(n) << 1) - 1;

return n ^ mask;

}

xwb1989 answered 2020-07-21T22:44:22Z

0 votes

public static int findComplement(int num) {

return (~num & (Integer.highestOneBit(num) - 1));

}

prashant answered 2020-07-21T22:44:37Z

0 votes

您可以尝试以下方法:

/**

* Flipping bits of a decimal Integer.

*/

public class FlipBits {

public static final char ONE_CHAR = '1';

public static final char ZERO_CHAR = '0';

static int flipBits(int n) {

String nBinary = Integer.toBinaryString(n);

System.out.println("Original number is decimal " + n + ", and binary " + nBinary);

char[] result = new char[nBinary.length()];

char[] nBinaryChars = nBinary.toCharArray();

for (int i = 0; i < nBinaryChars.length; i++) {

result[i] = nBinaryChars[i] == ONE_CHAR ? ZERO_CHAR : ONE_CHAR;

}

int resultDecimal = Integer.parseInt(String.valueOf(result), 2);

System.out.println("Flipped number in decimal is " + resultDecimal

+ ", and in binary is " + String.valueOf(result));

return resultDecimal;

}

public static void main(String[] args) {

int input = 21;

int flippedInteger = flipBits(input);

System.out.println(input + " becomes " + flippedInteger + " after flipping the bits.");

}

}

样本输出:

原始数字为十进制21,二进制为10101

十进制的翻转数字是10,二进制的是01010

翻转位后21变为10。

Vahid answered 2020-07-21T22:45:14Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值