~x + ~y ==〜(x + y)总是假的?

Ste*_*eve 153 c signed bit-manipulation twos-complement

此代码是否总是评估为false?这两个变量都是两个补码签名的整数.

~x + ~y == ~(x + y)
Run Code Online (Sandbox Code Playgroud)

我觉得应该有一些数字满足条件.我试过测试之间的数字-5000,5000但从未达到平等.有没有办法建立一个方程来找到条件的解?

将一个换成另一个导致我的程序中的一个阴险的错误?

Ale*_*ood 237

假设为了矛盾,存在一些x和一些y(mod 2 n)这样的

~(x+y) == ~x + ~y
Run Code Online (Sandbox Code Playgroud)

通过两个补码*,我们知道,

      -x == ~x + 1
<==>  -1 == ~x + x
Run Code Online (Sandbox Code Playgroud)

注意到这个结果,我们有,

      ~(x+y) == ~x + ~y
<==>  ~(x+y) + (x+y) == ~x + ~y + (x+y)
<==>  ~(x+y) + (x+y) == (~x + x) + (~y + y)
<==>  ~(x+y) + (x+y) == -1 + -1
<==>  ~(x+y) + (x+y) == -2
<==>  -1 == -2
Run Code Online (Sandbox Code Playgroud)

因此,矛盾.因此,~(x+y) != ~x + ~y对于所有xy(mod 2 n).


*有趣的是,在具有一个补码算术的机器上,相等实际上适用于所有xy.这是因为在一个人的补充下,~x = -x.因此,~x + ~y == -x + -y == -(x+y) == ~(x+y).

  • 当然,C不需要这种行为; 因为它不需要两个补码表示. (47认同)
  • 顺便说一下,对于一个人来说,平等是真的**.NOT操作实际上并未真正定义数字,因此将NOT与add相加会导致不同的行为,具体取决于数字的表示形式. (12认同)
  • 人们可以将问题重述为*无符号整数*然后二进制补码根本不会发挥作用. (9认同)
  • @BillyONeal,别担心,我只是在开玩笑,我很欣赏你提到它:).我会在遇到一台执行一个补码运算的机器的那天给你买一杯饮料......听起来怎么样?哈哈 (7认同)
  • 更简单,恕我直言:`~x == - (x + 1)`,所以`〜(x + y)== ~x + ~y`暗示` - (x + y + 1)== - (x + 1)+ - (y + 1)`暗示`-1 == -2` (5认同)
  • @AlexLockwood:我不是想成为那个"那个人".我不是说说两个人的补充是坏的; 只是说"这适用于两个补充机器"或答案中的那种效果很好.(你做了哪个,这就是为什么我没有向你投票:))我只想指出C确实允许签名号码的替代表示. (5认同)
  • 对于无符号整数,在Z_ {2 ^ n}中为-1 == 2 ^ n-1为真. (3认同)

dan*_*n04 113

两个人的补充

绝大多数计算机上,如果x是整数,则-x表示为~x + 1.同等地,~x == -(x + 1).在你的等式中进行这种替换给出了:

  • ~x + ~y ==〜(x + y)
  • - (x + 1)+ - (y + 1)= - ((x + y)+ 1)
  • -x - y - 2 = -x - y - 1
  • -2 = -1

这是一个矛盾,所以~x + ~y == ~(x + y)总是错误的.


也就是说,小学生会指出C不需要两个补码,所以我们也必须考虑......

一个人的补充

一个补充中,-x简单地表示为~x.零是一种特殊情况,具有all-0(+0)和all-1(-0)表示,但IIRC,C要求+0 == -0即使它们具有不同的位模式,所以这应该不是问题.刚刚替补~使用-.

  • ~x + ~y ==〜(x + y)
  • -x +(-y)= - (x + y)

这是真正的所有xy.

  • 实际上同时考虑两个补码和一个补码的答案+1. (13认同)
  • @ dan04,`+ 0 == -0`.最后在C中有意义的东西:) (13认同)

Pau*_*aul 32

只考虑两者的最右边xy(IE.如果x == 131101在基数2中,我们只查看最后一位,a 1)然后有四种可能的情况:

x = 0,y = 0:

LHS:~0 + ~0 => 1 + 1 => 10
RHS:〜(0 + 0)=> ~0 => 1

x = 0,y = 1:

LHS:~0 + ~1 => 1 + 0 => 1
RHS:〜(0 + 1)=> ~1 => 0

x = 1,y = 0:

我会把这个留给你,因为这是作业(提示:它与之前的x和y交换相同).

x = 1,y = 1:

我也会把这个留给你.

你也可以说最右边的位将一直在给定的任何可能的输入方程的左手边,右手边不同,所以你已经证明双方不相等的,因为他们至少是翻转一个位彼此.


Kar*_*han 27

如果位数是n

~x = (2^n - 1) - x
~y = (2^n - 1) - y


~x + ~y = (2^n - 1) +(2^n - 1) - x - y =>  (2^n + (2^n - 1) - x - y ) - 1 => modulo: (2^n - 1) - x - y - 1.
Run Code Online (Sandbox Code Playgroud)

现在,

 ~(x + y) = (2^n - 1) - (x + y) = (2^n - 1) - x - y.
Run Code Online (Sandbox Code Playgroud)

因此,它们总是不相等,相差1.

  • @nhahtdh以及如何在非固定宽度数上定义`~`操作? (4认同)

Meh*_*dad 27

暗示:

x + ~x = -1(mod 2 n)

假设问题的目标是测试你的数学(而不是你的阅读C规范技能),这应该可以帮助你找到答案.

  • @Billy:这就像说"只适合双臂人士". (12认同)
  • 只有两台补充机器.(C标准不要求) (2认同)
  • @ dan04:不,不是.我很乐意说所有签名的量级和补充表示都是从世界上消失的.但我这样说是错的.C标准不允许你做出这个假设; 因此,我会说在大多数情况下使得该假设的代码是错误的代码.(特别是当通常有更好的方法来处理有符号的数字而不是比特琐事;特别是当无符号数字在大多数情况下可能是更好的选择时) (2认同)

ype*_*eᵀᴹ 10

在一个和两个(甚至是42个)的补充中,这可以证明:

~x + ~y == ~(x + a) + ~(y - a)
Run Code Online (Sandbox Code Playgroud)

现在让a = y我们拥有:

~x + ~y == ~(x + y) + ~(y - y)
Run Code Online (Sandbox Code Playgroud)

要么:

~x + ~y == ~(x + y) + ~0
Run Code Online (Sandbox Code Playgroud)

因此,在两个补语中~0 = -1,命题是错误的.

在一个补充中~0 = 0,命题是正确的.


小智 7

根据Dennis Ritchie的书,C默认不实现二进制补码.因此,您的问题可能并非总是如此.


Adr*_*onk 5

MAX_INT是由表示的INT 011111...111(器,用于许多位有).然后,你知道,~x + x = MAX_INT~y + y = MAX_INT,所以你会因此肯定知道之间的差别~x + ~y,并~(x + y)1.


use*_*551 5

C不要求两个补码是实现的.但是,对于无符号整数,应用类似的逻辑.在这个逻辑下,差异总是1!