69

I have to flip all bits in a binary representation of an integer. Given:

10101

The output should be

01010

What is the bitwise operator to accomplish this when used with an integer? For example, if I were writing a method like int flipBits(int n);, what would go in the body? I need to flip only what's already present in the number, not all 32 bits in the integer.

Prince
  • 20,353
  • 6
  • 39
  • 59
Naftuli Kay
  • 87,710
  • 93
  • 269
  • 411
  • 3
    What does OP mean by "I need to flip only what's already present in the number, not all 32 bits in the integer."? If the number is "000101", does he expect "111010", or "000" as it is followed by "010" because the 1st one starts from 3rd LSB? Either way, it is inconsistent to the earlier statement "I have to flip all bits". – Salil Sep 29 '16 at 07:50

16 Answers16

86

The ~ unary operator is bitwise negation. If you need fewer bits than what fits in an int then you'll need to mask it with & after the fact.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    how about in scala? I got totally wrong result when i do ~22, i expect 9, but i get -23 – soMuchToLearnAndShare Dec 07 '21 at 23:07
  • just realised scala does not support unassigned int by default; so it treats everything signed. i guess i have to big shift left by 1 bit after doing the `~` to get what java or a human eyes would get. – soMuchToLearnAndShare Dec 08 '21 at 20:42
  • @soMuchToLearnAndShare I had the same problem (for me it was in Rust), and I had to bitshift by the length of my string (see here: https://stackoverflow.com/a/71248916/12069968). – Jake Ireland May 27 '22 at 08:00
40

Simply use the bitwise not operator ~.

int flipBits(int n) {
    return ~n;
}

To use the k least significant bits, convert it to the right mask.
(I assume you want at least 1 bit of course, that's why mask starts at 1)

int flipBits(int n, int k) {
    int mask = 1;
    for (int i = 1; i < k; ++i)
        mask |= mask << 1;

    return ~n & mask;
}

As suggested by Lưu Vĩnh Phúc, one can create the mask as (1 << k) - 1 instead of using a loop.

int flipBits2(int n, int k) {
    int mask = (1 << k) - 1;
    return ~n & mask;
}
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
George
  • 3,765
  • 21
  • 25
  • 1
    Unfortunately, that doesn't give me the expected value. The bitwise reversal of 26 should be 11, but I'm getting some crazy values when using `~`. Is there a way to make it only use the number of bits actually used in an integer? – Naftuli Kay Jun 14 '11 at 23:33
  • 2
    In java, `int`s are always 32 bits (2's compliment) regardless of the size of the number represented – Reese Moore Jun 14 '11 at 23:35
  • This was established as a given in the problem I need to solve. – Naftuli Kay Jun 14 '11 at 23:35
  • How can I get the smallest binary representation of an integer and flip the bits there? – Naftuli Kay Jun 14 '11 at 23:36
  • You need to and the return value by a mask this has as many 1s in its lower bits as there are digits to encode the input parameter. – Atreys Jun 14 '11 at 23:36
  • @TK perform a base 2 logarithm to get the number of bits needed. – Atreys Jun 14 '11 at 23:37
  • 6
    Btw the bitwise reversal of 26 is not 11, but 5. 26: 11010, ~26: 00101 = 5. – George Jun 14 '11 at 23:45
  • Call with `k` set to `(int) Math.ceil((Math.log(n+1) / Math.log(2)))`, or set the size of the mask inside flipBits – Atreys Jun 15 '11 at 12:53
  • 4
    to get a mask with k low bits set, use `(1 << k) - 1` instead of looping and set each bit. – phuclv Sep 14 '14 at 17:36
  • You are right, this seems to be a much better way to do it. Edited the answer to include your suggestion. – George Sep 15 '14 at 15:20
20

There is a number of ways to flip all the bit using operations

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
  • 525,659
  • 79
  • 751
  • 1,130
4

faster and simpler solution :

/* 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;
}
4

Well since so far there's only one solution that gives the "correct" result and that's.. really not a nice solution (using a string to count leading zeros? that'll haunt me in my dreams ;) )

So here we go with a nice clean solution that should work - haven't tested it thorough though, but you get the gist. Really, java not having an unsigned type is extremely annoying for this kind of problems, but it should be quite efficient nonetheless (and if I may say so MUCH more elegant than creating a string out of the number)

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
  • 29,040
  • 11
  • 82
  • 156
2

One Line Solution

int flippingBits(int n) {
   return n ^ ((1 << 31) - 1);
}
Ashwin
  • 7,277
  • 1
  • 48
  • 70
0

I have another way to solve this case,

public static int complementIt(int c){
 return c ^ (int)(Math.pow(2, Math.ceil(Math.log(c)/Math.log(2))) -1);
}

It is using XOR to get the complement bit, to complement it we need to XOR the data with 1, for example :

101 XOR 111 = 010

(111 is the 'key', it generated by searching the 'n' square root of the data)

if you are using ~ (complement) the result will depend on its variable type, if you are using int then it will be process as 32bit.

Rio
  • 27
  • 5
  • 1
    your way is extremely inefficient. To get 2^c simply use `1 << c`, which is hundreds of times faster than log, ceil and pow. Moreover it's completely exact while dealing with floating-point maths may get you into trouble – phuclv Sep 14 '14 at 17:40
0

As we are only required to flip the minimum bits required for the integer (say 50 is 110010 and when inverted, it becomes 001101 which is 13), we can invert individual bits one at a time from the LSB to MSB, and keep shifting the bits to the right and accordingly apply the power of 2. The code below does the required job:

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;
        }
0
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));
        }
    }
}
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • 1
    While code-only answers are valid for simple contexts, if they are correct; please have in mind that they are unrecommended. Always try to provide explanation of at least *what* the code is doing, and *how* or *why* it's doing it, in at least the most critical parts of the code. In this specific case, links to the official documentation for [`BigInteger(String)`](https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#BigInteger-java.lang.String-) and [`Scanner.nextInt()`](https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#nextInt--) are also recommended. – CosmicGiant Feb 11 '16 at 16:43
0

The implementation from 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;
}

Base on my experiments on my laptop, the implementation below was faster:

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;
}

Not sure what's the reason behind it - as it may depends on how the java code is interpreted into machine code...

0

If you just want to flip the bits which are "used" in the integer, try this:

public int flipBits(int n) {
    int mask = (Integer.highestOneBit(n) << 1) - 1;
    return n ^ mask;
}
xwb1989
  • 233
  • 1
  • 14
0
public static int findComplement(int num) {
    return (~num & (Integer.highestOneBit(num) - 1));
}
prashant
  • 348
  • 3
  • 13
0
int findComplement(int num) {
        int i = 0, ans = 0;
        while(num) {
            if(not (num & 1)) {
                ans += (1 << i);
            }
            i += 1;
            num >>= 1;
        }
        return ans;
}
Rajan saha Raju
  • 794
  • 7
  • 13
  • 1
    While this code may provide a solution to the question, it's better to add context as to why/how it works. This can help future users learn, and apply that knowledge to their own code. You are also likely to have positive feedback from users in the form of upvotes, when the code is explained. – borchvm May 06 '20 at 08:22
0

I'd have to see some examples to be sure, but you may be getting unexpected values because of two's complement arithmetic. If the number has leading zeros (as it would in the case of 26), the ~ operator would flip these to make them leading ones - resulting in a negative number.

One possible workaround would be to use the Integer class:

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;
}

I don't have a java environment set up right now to test it on, but that's the general idea. Basically just convert the number to a string, cut off the leading zeros, flip the bits, and convert it back to a number. The Integer class may even have some way to parse a string into a binary number. I don't know if that's how the problem needs to be done, and it probably isn't the most efficient way to do it, but it would produce the correct result.

Edit: polygenlubricants' answer to this question may also be helpful

Community
  • 1
  • 1
Ben Sutton
  • 202
  • 2
  • 12
  • @Vuntic Well like I said, it probably isn't the best way to do it, but it would get the job done. It's really just a question of how you want to represent the data. It would also work to left-shift the number until the leading zeros are gone, flip the bits, and then right-shift it back, but that wouldn't end up being much simpler. When you have to do something in a high-level language like Java that's better suited for a low-level language like C, the solution isn't always going to be as elegant. – Ben Sutton Jun 15 '11 at 00:46
  • 1
    @Ben Apart from the fact that Java doesn't have an unsigned type (not really problematic here but a bit annoying) the solution is the same in C or any other language you can think of if it allows bit twiddling - cheap excuse ;) But sure taking a few ns more to execute such a function won't matter and the solution is easy and simple to understand.. not bad in itself - it just misses this certain elegance of a good mathematical solution imho – Voo Jun 15 '11 at 01:25
  • @Voo, In Java using Strings like this would take tens of micro-seconds. `~` takes hundreds of pico-seconds. Strings make more of difference in Java than they do in C. – Peter Lawrey Jun 15 '11 at 05:40
  • @Peter I assumed I wouldn't be taken literally with "won't take too long". Also considering that the frequency of a modern CPU is still only about <5*10^9Hz picoseconds are a bit "optimistic" ;) – Voo Jun 15 '11 at 18:22
  • @Voo, most modern CPUs are better 2-3.3 GHz some as high as 5.1 GHz. A bit wise invert is typically a single clock cycle instruction. – Peter Lawrey Jun 15 '11 at 18:42
  • @Peter Yep, but sadly 1Ghz means that the execution of one cycle takes 1ns not 1ps. You'd need a CPU with 1Thz to finish one clock cycle in 1ps. I don't see why we should argue about 10% speed differences when the fastest CPU I know of (some p4 oced to 9ghz or so) is still an order of magnitude too slow – Voo Jun 15 '11 at 22:49
  • @Voo, a 1.1 GHz (speed of a smart phone) processor still has a 900 ns clock cycle, a 3.3 GHz is about 300 ps. There are not many PCs which are 1 GHz. – Peter Lawrey Jun 16 '11 at 20:11
0
          Binary 10101 == Decimal 21
  Flipped Binary 01010 == Decimal 10

One liner (in Javascript - You could convert to your favorite programming language )

10 == ~21 & (1 << (Math.floor(Math.log2(21))+1)) - 1

Explanation:

 10 == ~21 & mask

mask : For filtering out all the leading bits before the significant bits count (nBits - see below)

How to calculate the significant bit counts ?

Math.floor(Math.log2(21))+1   => Returns how many significant bits are there (nBits)

Ex:

0000000001 returns 1

0001000001 returns 7

0000010101 returns 5

(1 << nBits) - 1         => 1111111111.....nBits times = mask
SridharKritha
  • 8,481
  • 2
  • 52
  • 43
0

It can be done by a simple way, just simply subtract the number from the value obtained when all the bits are equal to 1 . For example: Number: Given Number Value : A number with all bits set in a given number. Flipped number = Value – Number. Example : Number = 23, Binary form: 10111 After flipping digits number will be: 01000 Value: 11111 = 31

We can find the most significant set bit in O(1) time for a fixed size integer. For example below code is for a 32-bit integer.

int setBitNumber(int n)
{
n |= n>>1;
n |= n>>2;
n |= n>>4;
n |= n>>8;
n |= n>>16;
n = n + 1;
return (n >> 1);
}