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 ith 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 ith 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
Assisted me a lot, just what I was looking for : D.