首页 > 解决方案 > 如何在 Perl 中将总线一元化和/减少一点?

问题描述

我有一个变量$A = 0x3

我想$B成为一个,即与变量的所有位A

另外我该怎么做OR

已经试过了$B &= $A,不行。

标签: perlbit-manipulation

解决方案


如果$A是一个 8 位值,并且如果您想将所有 8 位相互与,0除非所有 8 位都是1

+----+----+----+----+----+----+----+----+---------------------------------------+
| A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | A7 & A6 & A5 & A4 & A3 & A2 & A1 & A0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
|  0 |  0 |  0 |  0 |  0 |  0 |  0 |  0 |                                     0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
|  0 |  0 |  0 |  0 |  0 |  0 |  0 |  1 |                                     0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
|  0 |  0 |  0 |  0 |  0 |  0 |  1 |  0 |                                     0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
|  0 |  0 |  0 |  0 |  0 |  0 |  1 |  1 |                                     0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
|  0 |  0 |  0 |  0 |  0 |  1 |  0 |  0 |                                     0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
...
+----+----+----+----+----+----+----+----+---------------------------------------+
|  1 |  1 |  1 |  1 |  1 |  1 |  1 |  0 |                                     0 |
+----+----+----+----+----+----+----+----+---------------------------------------+
|  1 |  1 |  1 |  1 |  1 |  1 |  1 |  1 |                                     1 |
+----+----+----+----+----+----+----+----+---------------------------------------+

这意味着您将得到0unless$A等于0b11111111aka 0xFFaka 255。这意味着您可以简单地使用以下内容:

my $B = $A == 255 ? 1 : 0;

上述解决方案比使用按位运算更简单、更快捷,但可以使用这些。

为了隔离一点,使用以下内容:

( $A >> $bitnum ) & 1

所以以下将与 8 位一起:

my $B =
     ( ( $A >> 7 ) & 1 )
   & ( ( $A >> 6 ) & 1 )
   & ( ( $A >> 5 ) & 1 )
   & ( ( $A >> 4 ) & 1 )
   & ( ( $A >> 3 ) & 1 )
   & ( ( $A >> 2 ) & 1 )
   & ( ( $A >> 1 ) & 1 )
   & ( ( $A >> 0 ) & 1 );

删除冗余& 1给我们以下简化的解决方案:

my $B = 1
   & ( $A >> 7 )
   & ( $A >> 6 )
   & ( $A >> 5 )
   & ( $A >> 4 )
   & ( $A >> 3 )
   & ( $A >> 2 )
   & ( $A >> 1 )
   & ( $A >> 0 );

事实上,因为我们从 8 位值开始,所以以下内容就足够了:

my $B =
     ( $A >> 7 )
   & ( $A >> 6 )
   & ( $A >> 5 )
   & ( $A >> 4 )
   & ( $A >> 3 )
   & ( $A >> 2 )
   & ( $A >> 1 )
   & ( $A >> 0 );

我们可以通过一次 ANDing 多个位来改进这一点!

 my $B = $A;
 $B &= $B >> 4;
 $B &= $B >> 2;
 $B &= $B >> 1;

推荐阅读