如何考虑简单操作的位操作?

Moe*_*oeb 3 c bit-manipulation

例如:

unsigned int a;    // value to merge in non-masked bits
unsigned int b;    // value to merge in masked bits
unsigned int mask; // 1 where bits from b should be selected; 0 where from a.
unsigned int r;    // result of (a & ~mask) | (b & mask) goes here

r = a ^ ((a ^ b) & mask); 
Run Code Online (Sandbox Code Playgroud)

根据掩码合并来自两个值的位.

[取自这里 ]

在这种情况下,我可以看到它有效,但我不确定逻辑是什么?而且我不确定我是否可以从头开始创建自己的位操作.我该如何开始思考?

Abe*_*bel 7

在这种情况下,铅笔和纸有助于提高效果.我经常写下来:

a        = 10101110
b        = 01100011
mask     = 11110000

a ^ b    = 10101110
           01100011
           --------
x =>       11001101

x & mask = 11001101
           11110000
           --------
x =>       11000000

a ^ x    = 11000000
           10101110
           --------
x =>       01101110
Run Code Online (Sandbox Code Playgroud)

(最终x是你的r)
我不知道这是你所追求的结果,但这就是它的作用.当我不理解按位操作时,写出来通常会有所帮助.


Pod*_*Pod 5

在这种情况下,我可以看到它有效,但我不确定逻辑是什么?而且我不确定我是否可以从头开始创建自己的位操作.我该如何开始思考?

人们回答了你的第一个问题 - 解释逻辑.我希望能向你展示一个非常基本的,冗长但标准的方法,使任何一点点操作.(注意,一旦你习惯了比特,你就会开始考虑&和|直接思考而不做这些废话).

  1. 找出你想要做什么的操作.
  2. 写出一个完整的真值表.
  3. 要么直接从表格中读取产品总数,要么制作卡诺图.该公里将减少最终的方程AXB一个不少.
  4. ???
  5. 利润

得出你给出的例子.即,掩码从A或B中选择位.(0是A,1是B)

该表用于每个输入1位.我不会做多于一点,因为我不想浪费我的时间:)(为什么?2 ^(2bits*3inputs)= 64个案例:( 2 ^(3bits*3inputs)= 512个案例:(( )

但好消息是,在这种情况下,操作独立于位数,因此1位示例是100%罚款.事实上,我推荐:)

| A | B | M || R |
============++====
| 0 | 0 | 0 || 0 |
| 0 | 0 | 1 || 0 |
| 0 | 1 | 0 || 0 |
| 0 | 1 | 1 || 1 |
| 1 | 0 | 0 || 1 |
| 1 | 0 | 1 || 0 |
| 1 | 1 | 0 || 1 |
| 1 | 1 | 1 || 1 |
Run Code Online (Sandbox Code Playgroud)

希望你能看到这个真值表的工作原理.

如何从中得到一个表达式?两种方法:KMaps和副手.我们先做,我们先做吧?:)

看看R为真的点,我们看到:

| A | B | M || R |
============++====
| 0 | 1 | 1 || 1 |
| 1 | 0 | 0 || 1 |
| 1 | 1 | 0 || 1 |
| 1 | 1 | 1 || 1 |
Run Code Online (Sandbox Code Playgroud)

由此我们可以表达一种表达:

R = (~A &  B &  M) |
    ( A & ~B & ~M) |
    ( A &  B & ~M) |
    ( A &  B &  M) |
Run Code Online (Sandbox Code Playgroud)

希望你能看到它是如何工作的:只是或者在每种情况下看到的完整表达式.完全我暗示你不需要变量.

我们在python中尝试一下:

a = 0xAE #10101110b
b = 0x64 #01100011b
m = 0xF0 #11110000b
r = (~a & b & m) | ( a & ~b & ~m) | ( a &  b & ~m) | ( a &  b &  m)
print hex(r)
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

0x6E
Run Code Online (Sandbox Code Playgroud)

这些数字来自亚伯的例子.输出是0x6E,即01101110b.所以它奏效了!欢呼.(ps,如果你想这样做,可以从第一个表中导出~r的表达式.只需采用r为0的情况).

你所做的这个表达式是一个布尔"产品之和",也就是析取范式,虽然DNF实际上是使用一阶谓词逻辑时使用的术语.这个表达也非常不合情理.将它缩小是一件很麻烦的事情,如果你学习编译器或硬件课程,你可以在Uni'的CS学位上做50万次.(强烈推荐 :))

所以,让我们做一些布尔代数魔法(不要试着遵循这个,这是浪费时间):

(~a & b & m) | ( a & ~b & ~m) | ( a &  b & ~m) | ( a &  b &  m)
|= ((~a & b & m) | ( a & ~b & ~m)) | ( a &  b & ~m) | ( a &  b &  m)
Run Code Online (Sandbox Code Playgroud)

采取我做的第一个子条款:

((~a & b & m) | ( a & ~b & ~m))

|= (~a | (a & ~b & ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
|= ((~a | a) & (a | ~b) &( a | ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
|= (T & (a | ~b) &( a | ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
|= ((a | ~b) & (a | ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
Run Code Online (Sandbox Code Playgroud)

等等等.这是你猜不到的大量繁琐的一点.所以,只需在您选择的网站中敲击表达,这将告诉您

r = (a & ~m) | (b & m)
Run Code Online (Sandbox Code Playgroud)

欢呼!正确的结果.注意,甚至可能会给你一个涉及XOR的表达,但是谁在乎?事实上,有些人做,与表达andS和ors是4点的操作(1 or,2 and,1 neg),而r = a ^ ((a ^ b) & mask)为3(2 xor,1 and).

现在,你如何用kmaps做到这一点?好吧,首先你需要知道如何制作它们,我会让你这样做.:)只是谷歌为它.有软件可用,但我认为最好手动完成 - 它更有趣,程序不允许你作弊.作弊?好吧,如果你有很多输入,通常最好减少表格,如下所示:

| A | B | M || R |
============++====
| X | X | 0 || A |
| X | X | 1 || B |
Run Code Online (Sandbox Code Playgroud)

例如64个案例表?

| A1| A0| B1| B0| M1| M0|| R1| R0|
========================++========
| X | X | X | X | 0 | 0 || A1| A0|
| X | X | X | X | 0 | 1 || A1| B0|
| X | X | X | X | 1 | 0 || B1| A0|
| X | X | X | X | 1 | 1 || B1| B0|
Run Code Online (Sandbox Code Playgroud)

在这个例子中归结为4个案例:)

(其中X是"不关心".)然后将该表放在Kmap中.再一次,练习让你锻炼[即,我忘记了如何做到这一点].

希望你现在可以在给定一组输入和一组预期输出的情况下推导出你自己的布尔疯狂.

玩得开心.