【问题标题】:Diffrent usage of &- operator&- 运算符的不同用法
【发布时间】:2020-11-28 19:55:17
【问题描述】:

看下面的代码:

#include <stdio.h>

int main()
{
    int num, sum;
    scanf("%d", &num);
    sum = num - (num&-num);
    printf("%d", sum);
    return 0;
}

sum = num - (num&amp; - num) 行以二进制格式返回给定数字的值,没有最后一个 1。例如,如果 num 等于 6(110),它将给出没有最后一个 1 的值。在这种情况下,100 等于 4。 我的问题是&amp;- 是如何工作的,我们如何在八进制数字系统中做同样的事情?

【问题讨论】:

  • num - (num &amp; (-num)); 更清晰。
  • 您从哪里了解到&amp;-“运营商”?
  • @Jabberwocky - 可能只是 --&gt; operator 的表亲。
  • @Jabberwocky 我在土耳其国家信息奥赛上看到了。

标签: c binary octal


【解决方案1】:

这里有两个独立的运算符:按位与运算符&amp; 和一元否定运算符-。所以有问题的行实际上是:

sum = num - (num & -num);

假设整数以二进制补码表示形式存储,取反一个值意味着反转所有位并加一。

如果num 是 6,(二进制 00000110),-num 是 -6,即 11111010。然后在这两个值之间执行按位与会导致二进制的 00000010 是十进制的 2,所以 @ 987654326@ 是 6 - 2 即 4。

【讨论】:

  • 一般来说,模式x&amp;-x 是“值x 的最低设置位,本身”,并且是标准的成语。
  • 虽然这里的示例是减去它以删除最低位,但您也可以只使用 x&amp;(x-1) 来获取一个值,该值是删除了最低设置位的输入。
【解决方案2】:

没有&amp;- 运算符。 num - (num&amp;-num)num - (num &amp; -num),其中&amp; 执行num 及其否定-num 的按位与。

考虑一些二进制数,例如 0011 0011 1100 11002(用于方便可视化的空格)。其负数为 -0011 0011 1100 11002。但是,我们通常使用二进制补码表示负数,其中添加了 2 的幂。对于 16 位格式,我们添加 216,即 1 0000 0000 0000 00002。因此,要表示 -0011 0011 1100 11002,我们使用 1 0000 0000 0000 00002 + -0011 0011 1100 11002 = 1100 1100 0011 01002.

观察这个减法中发生了什么,从右边逐列:

  • 在最右边的列中,我们有 0−0,即 0。
  • 下一列也有 0−0,产生 0。
  • 下一列有 0-1。这将产生 1,并从左侧的列借位。
  • 下一列有 0-1-1(其中第二个 -1 是借位)。这将产生 0 与另一个借位。
  • 因为被减数(被减去的数字)在最初的 1 之前都是零,所以这个借位永远不会满足,所以它会传播到整个位。

因此结果是:

  • 从右边开始,0 仍然是 0。
  • 第一个 1 保持为 1 但启动借用链。
  • 由于借位,该位左侧的所有位都从 0 翻转到 1 或从 1 翻转到 0。

因此,减数(被减去的数字)和结果在第一个 1 左边的所有位上都不同。它们在第一个 1 的右边都有 0。所以他们都设置的唯一位是第一个。

因此,当使用二进制补码时,num &amp; -num 的结果是num 中设置的最低 1 位。

然后num - (num &amp; -num)num 中减去该位,将其保留为num,其最低1 位更改为0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2020-12-17
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    相关资源
    最近更新 更多