This is a post to present one method to inverse the bit pattern of an input number, the bitwise not operation on a bit pattern. I am presenting one method which i figured out.

### The Idea

We first take a bitstring from the user and store it into a shell variable. Then we manually scan each bit of this binary string and inspecting the value of the currently scanned bit symbol (0 or 1) we make another string with the opposite bit symbol at that position. At the end of the bit string scanning the second shell variable would contain the inverted bit pattern of the bit string. The implementation is shown below.

### Sourcecode

#!/bin/bash num=$1 if [ -z $num ] then echo "$0 <number_in_decimal>" echo "Output would be the 1's compliment of the input" exit fi i=0 flag=1 inv_bit="" curr_bit=0 while [ true ] do curr_bit=${num:$i:1} if [ -z $curr_bit ] then break fi if [ $curr_bit -eq 0 ] then inv_bit=${inv_bit}1 elif [ $curr_bit -eq 1 ] then inv_bit=${inv_bit}0 else flag=0 break fi i=$((i+1)) done if [ $flag -eq 1 ] then echo "~$num is $inv_bit" else echo "Invalid input" fi

### Description

First there is a minimal error checking which only allow if some non-zero string is provided in the command line. The input number from command line is taken into the shell variable `num`. The `flag` indicates if the inverted bit string complement output is valid and initially it is set to 1 indicating valid. The inverted bit pattern would be stored into the shell variable `inv_bit` which is initialized as empty string. The `curr_bit` would be used to hold the currently scanned bit position of the `num`. `i` is initialized to zero, which would be used to index into the `num` bit positions. Please note that the binary bit pattern is scanned as a string from left to right (index 0 starts at the leftmost position).

The `while` loop is entered. Starting from 0, at each iteration the `i`^{th} bit from `num` is cut out by bash builtin shell substitution syntax `${num:$i:1}` where `$i` is the base and 1 is the offset of the substring to be cut out from `num`. In effect it gets the `i`^{th} character of the string and saves into `curr_bit` .

If `curr_bit` is a zero string, then `num` has no more bits to be scanned and the process finishes. If `curr_bit` is 1 then we append 0 to the current value `inv_bit`, and if `curr_bit` is 0 then we need to append 1 to the current value of `inv_bit`. Any other symbol for `curr_bit` sets the `flag=0` and ends the process. To append the found bit into the existing inverse bit pattern we do `inv_bit=${inv_bit}0` and `inv_bit=${inv_bit}1` as needed. This appends the newly found inverted bit at the end of the intermediate result stored in `inv_bit` . The index `i` is incremented.

After the loop breaks (when the `curr_bit` becomes zero string), if `flag` is 1 , then the inverse bit of the input bit pattern is output, or an error message is printed otherwise.

### Output

Here are some sample output:

[phoxis@localhost disk]$ ./inv_1.sh 1010 ~1010 is 0101 [phoxis@localhost disk]$ ./inv_1.sh 1101 ~1101 is 0010 [phoxis@localhost disk]$ ./inv_1.sh 1111 ~1111 is 0000 [phoxis@localhost disk]$ ./inv_1.sh 11010010 ~11010010 is 00101101 [phoxis@localhost disk]$ ./inv_1.sh 10010011010011 ~10010011010011 is 01101100101100 [phoxis@localhost disk]$ ./inv_1.sh 110212 Invalid input

### Fixed Length Bit String

To find a one’s complement of an integer with this method, then we need to fix the length of the bitpattern, and consider the MSB as the signed bit. This can be implemented by doing a minor modification to the above script which is as follows. We can make the while loop run a fixed number of times, say 32 times for to find the one’s complement of a 32bit integer. While the input string does not end like the above process we will append the opposite bit in the destination inverse bit pattern variable. When the input number has ended ie. the `curr_bit` is a zero string and `i` is still not 32, then we need to *prepend* 1s to the inverted bit string calculated till now. This is done by placing the 1 before the `inv_bit` like `inv_bit=1$inv_bit` . The modified script is shown below:

#!/bin/bash num=$1 if [ -z $num ] then echo "$0 <number_in_decimal>" echo "Output would be the 1's compliment of the input" exit fi i=0 flag=1 inv_bit="" curr_bit=0 while [ $i -lt 32 ] do curr_bit=${num:$i:1} if [ -z $curr_bit ] then inv_bit=1$inv_bit elif [ $curr_bit -eq 0 ] then inv_bit=${inv_bit}1 elif [ $curr_bit -eq 1 ] then inv_bit=${inv_bit}0 else flag=0 break fi i=$((i+1)) done if [ $flag -eq 1 ] then echo "~$num is $inv_bit" else echo "Invalid input" fi

### Output

Here is some sample output of this code

[phoxis@localhost disk]$ ./inv_2.sh 1010 ~1010 is 11111111111111111111111111110101 [phoxis@localhost disk]$ ./inv_2.sh 10001101001 ~10001101001 is 11111111111111111111101110010110 [phoxis@localhost disk]$ ./inv_2.sh 11111111111111111111111111101101 ~11111111111111111111111111101101 is 00000000000000000000000000010010

### Comments

We can accept any other base integers and first convert it into binary bit pattern with `bc` and then apply the above module(s).

Good one!

+1