【问题标题】:C Bitwise operations left shift and bitwise ORC按位运算左移和按位或
【发布时间】:2018-12-03 03:07:14
【问题描述】:

很短,我在理解这段代码的工作原理时遇到了问题,它比我的 20 行左右的代码更有效地获得相同的结果。我了解左移应该如何工作以及按位或,但希望得到一些指导,以了解两者如何结合在一起以使 for 循环中的行工作。 代码旨在接收给定大小(计数)的位(位)数组并返回位的整数值。

unsigned binary_array_to_numbers(const unsigned *bits, size_t count) {
    unsigned res = 0;
    for (size_t i = 0; i < count; i++)
        res = res << 1 | bits[i]; 
    return res;
}

编辑:根据要求,我的新手解决方案仍然通过了所有测试:添加是可能分配给 bits[] 的示例

unsigned binary_array_to_numbers(const unsigned *bits, size_t count)
{
        int i, j = 0;
        unsigned add = 0;
        for (i = count - 1; i >= 0; i--){
                if(bits[i] == 1){
                        if(j >= 1){
                                j = j * 2;
                                add = add + j;
                        }
                        else{
                                j++;
                                add = add + j;

                        }
                }
                else {
                        if( j>= 1){
                                j = j * 2;
                        }
                        else{
                                j++;
                        }
                }
        }

        return add;
}

void main(){
        const unsigned bits[] = {0,1,1,0};
        size_t count = sizeof(bits)/sizeof(bits[0]);
        binary_array_to_numbers(bits, count);
}

【问题讨论】:

  • 你能显示一个示例调用吗?也许你的 20 行?
  • 根据请求编辑。
  • 两张反对票?也许我不明白这个网站应该如何运作?我认为堆栈溢出是针对特定代码相关的问题。这篇stackoverflow.com/questions/141525/… 的帖子是历史悠久的经典之作,获得了 1230 次赞成票,本质上是“位移如何工作?”可以在许多其他地方找到答案的一般问题。我发布了一个特定的用例,为什么不赞成?
  • 你确定是unsigned res = 0;
  • 是的,它是 CodeWars 上 C katas 之一的排名第一的答案。当您在那里提交答案时,它会经过非常彻底的测试以通过所有边缘情况。刚刚意识到我在测试期间将返回类型更改为int,只是将其更改回来,我已经仔细检查了代码是否与原始答案相同。

标签: c bit-manipulation bit-shift


【解决方案1】:

细分:

  • 二进制数的每个左移操作都会有效地相乘 2 0111(7) &lt;&lt; 1 = 1110(14)
  • 考虑 rhubarbdog 的回答 - 该操作可以看作是两个独立的操作。首先左移(乘以 2),然后与正在检查的当前位进行或运算
  • PC 不区分显示的值和二进制 数字的表示

让我们试着回顾一个案例——您的输入是:

bits = {0, 1, 0, 1};
count = 4;
unsigned binary_array_to_numbers(const unsigned *bits, size_t count) {
    unsigned res = 0;
    for (size_t i = 0; i < count; i++)
        res = res << 1 // (a)
        res = res | bits[i]; /* (b) according to rhubarbdog answer */
    return res;
}

迭代 0:
- 位[i] = 0;
- (a) 资源 = b0; (左移 0)
- (b) 资源 = b0; (按位或与 0)

迭代 1:
- 位[i] = 1;
- (a) 资源 = b0; (左移 0)
- (b) 资源 = b1; (按位或与 1)

迭代 2:
- 位[i] = 0;
- (a) 资源 = b10; (左移 1 - 十进制值为 2)
- (b) 资源 = b10; (按位或与 0)

迭代 3:
- 位[i] = 1;
- (a) 资源 = b100; (左移 1 - 十进制值为 4)
- (b) 资源 = b101; (按位或与 1)

res 的最终结果是二进制(101)和十进制(5),正如人们所期望的那样 注意:必须使用unsigned,因为如果MSB 为1,则有符号值将被解释为负值

希望对您有所帮助...

【讨论】:

  • 这就是我所需要的,现在一步一步解释这个是有道理的。有时,对于熟悉的人来说,有些事情似乎很清楚,但对于新手来说,它就是不明白。感谢您抽出时间提供帮助。
【解决方案2】:

将它们视为 2 个操作,我将 res= ... 重写为 2 行

res = res << 1
res = res | 1

第一次通过 res 设置为 1,下一次转移 *2 然后因为它现在甚至是 +1

【讨论】:

  • 因此,如果bits[i] 为1,那么它与1 相或,所以它仍然为1,shift 为1,那么如果res 为0,那么res 如何获得一个值?我对此感到困惑,因此您将 res(0) 移动了 shift(1)。 0 是左移一位还是不是 0?对不起,我这里有一个逻辑空白,你能帮我补一下吗?
  • 我知道左移等价于左操作数* 2^右操作数。但是 0 * 2^1 是 0。我错过了一些东西。
  • @DocSpiegel 我已经编辑了我的答案,你可能想再看一遍
  • 如果你能快速解释一下,我会接受答案,如果 res = 0 所以 0000 0000 左移如何使它变为 1?这不会导致一个 0 脱落并在另一端被另一个替换吗?
  • 左移不会变成 1 它是按位或 1 res = res | 1
猜你喜欢
  • 1970-01-01
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多