&- 运算符的不同用法
Diffrent usage of &- operator
看下面的代码:
#include <stdio.h>
int main()
{
int num, sum;
scanf("%d", &num);
sum = num - (num&-num);
printf("%d", sum);
return 0;
}
行sum = num - (num& - num)
returns给定数字的二进制格式的最后一个1的值。例如,如果 num 等于 6(110),它将给出没有最后一个 1 的值。在这种情况下,100 等于 4。
我的问题是 &-
是如何工作的,我们如何在八进制数字系统中做同样的事情?
这里有两个独立的运算符:按位与运算符 &
和一元取反运算符 -
。所以有问题的行实际上是:
sum = num - (num & -num);
假设整数以二进制补码表示形式存储,取负值意味着反转所有位并加一。
在 num
为 6(二进制 00000110)的情况下,-num
为 -6 即 11111010。然后在这两个值之间执行按位与运算会得到二进制形式的 00000010,即2 十进制,所以 num - (num & -num)
是 6 - 2 即 4.
没有&-
运算符。 num - (num&-num)
是 num - (num & -num)
,其中 &
执行 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 1100 2 = 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 & -num
的结果是num
中设置的最低1位。
然后num - (num & -num)
从num
中减去这个位,留下num
,最低1位变为0。
看下面的代码:
#include <stdio.h>
int main()
{
int num, sum;
scanf("%d", &num);
sum = num - (num&-num);
printf("%d", sum);
return 0;
}
行sum = num - (num& - num)
returns给定数字的二进制格式的最后一个1的值。例如,如果 num 等于 6(110),它将给出没有最后一个 1 的值。在这种情况下,100 等于 4。
我的问题是 &-
是如何工作的,我们如何在八进制数字系统中做同样的事情?
这里有两个独立的运算符:按位与运算符 &
和一元取反运算符 -
。所以有问题的行实际上是:
sum = num - (num & -num);
假设整数以二进制补码表示形式存储,取负值意味着反转所有位并加一。
在 num
为 6(二进制 00000110)的情况下,-num
为 -6 即 11111010。然后在这两个值之间执行按位与运算会得到二进制形式的 00000010,即2 十进制,所以 num - (num & -num)
是 6 - 2 即 4.
没有&-
运算符。 num - (num&-num)
是 num - (num & -num)
,其中 &
执行 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 1100 2 = 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 & -num
的结果是num
中设置的最低1位。
然后num - (num & -num)
从num
中减去这个位,留下num
,最低1位变为0。