# How to Inverse Bit!

I am just curious.

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

~ fantasy ~
LVL 5
###### Who is Participating?

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

in other words, split into characters, reverse that array, and join them together with an empty string.
0
Author Commented:
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
Commented:
ah ok! then use tr:

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

0

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

OwnerCommented:
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
Commented:
the [] in the tr are unnecessary
0
Commented:
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
OwnerCommented:
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
###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.