Solved

# How to Inverse Bit!

Posted on 2003-11-11
Medium Priority
662 Views
I am just curious.

I have a string (\$str = "0101001000101001")
How can I invert all the bit in one line of code?

~ fantasy ~
0
Question by:fantasy1001
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points

LVL 18

Expert Comment

ID: 9729748
\$rev = join '', reverse split //, \$str;

in other words, split into characters, reverse that array, and join them together with an empty string.
0

LVL 5

Author Comment

ID: 9729831
I want to invert every bit like: 1010110111010110 the reverse the bit order.
If implement at your method, it reverse the string which can be done with

\$str = reverse \$str;

~ fantasy ~
0

LVL 18

Accepted Solution

kandura earned 225 total points
ID: 9730062
ah ok! then use tr:

\$str =~ tr/[01]/[10]/;

0

LVL 20

Expert Comment

ID: 9731466
You can use 'pack' and 'unpack' to convert between bit vectors and these 0-and-1 strings. Once in the form of a bit vector, you can manipulate them with 'vec' operations (to select a sub-range of the bit vector) and with the logical operators & (AND), | (OR), ^ (XOR), and -- the operation you're talking about here -- ~ (NOT).

Obviously, there's overhead involved in going to and from bit vectors, but if you have a lot of logical operations, they are considerably more efficient.
0

LVL 84

Expert Comment

ID: 9734636
the [] in the tr are unnecessary
0

LVL 18

Expert Comment

ID: 9734872
jmcg, ozo, you are both right. The 'pack' way offers a lot more flexibility. The [] are not needed in this tr.

However, I timed this:

use Benchmark qw/timethese cmpthese/;
\$|++;
\$s = '0101001000101001';

printf "s:      %-20s\$/", \$s;
printf "tr s:   %-20s\$/", with_tr();
printf "pack s: %-20s\$/", with_pack();

\$t = timethese(1000000, {
tr            => \&with_tr,
tr_nb      => \&with_tr_nb,
pack      => \&with_pack,
});
cmpthese(\$t);

sub with_tr {
my \$r = \$s;
\$r =~ tr/[01]/[10]/;
\$r;
}

sub with_tr_nb {
my \$r = \$s;
\$r =~ tr/01/10/;
\$r;
}

sub with_pack {
return unpack("b*", ~ pack("b*", \$s));
}

and got these results:
s:      0101001000101001
tr s:   1010110111010110
pack s: 1010110111010110
Benchmark: timing 1000000 iterations of pack, tr, tr_nb...
pack:  5 wallclock secs ( 5.14 usr +  0.00 sys =  5.14 CPU) @ 194666.15/s (n=1000000)
tr:  1 wallclock secs ( 2.13 usr +  0.00 sys =  2.13 CPU) @ 468823.25/s (n=1000000)
tr_nb:  2 wallclock secs ( 2.08 usr +  0.00 sys =  2.08 CPU) @ 480076.81/s (n=1000000)
Rate  pack    tr tr_nb
pack  194666/s    --  -58%  -59%
tr    468823/s  141%    --   -2%
tr_nb 480077/s  147%    2%    --

So at least my proposed version is the quickest :)
0

LVL 20

Expert Comment

ID: 9735976
Oh, the overhead of pack and unpack is considerable. It's only worthwhile doing the conversion if you have a number of bit operations to accomplish or there is some space-saving reason to use bitvectors. The conversion in one direction alone is probably just as expensive as the entire tr operation, which is borne out by your results.

What's curious is that adding the brackets somehow reduces the time it takes to perform the tr operation. That is a surprising result.
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. Iâ€¦