〜x +〜y ==〜(x + y)は常にfalseですか?


153

このコードは常にfalseと評価されますか?どちらの変数も2の補数の符号付き整数です。

~x + ~y == ~(x + y)

条件を満たす数はあるはずだと思います。私は間の数字をテストしようとした-50005000が、平等を達成したことがありません。条件の解を見つけるための方程式を設定する方法はありますか?

片方をもう片方に交換すると、プログラムに潜むバグが発生しますか?


6
証明か何か欲しいですか?
Alvin Wong

26
符号付き整数オーバーフローの場合、技術的に未定義の動作であることに注意してください。そのため、true厳密な2の補数を仮定できない場合でも、戻ることができます。
Mysticial 2012年

1
@AlvinWongはい、説明がいいでしょう
Steve

1
@Steve:すべての通常の容疑者(-1、0、1、2など)をすべての組み合わせで試したこと、および小さな単語サイズの問題を "解決"しようとしたことを実証できます( 3ビット?4ビット?)。これは、私たちが誰かが最初に自分で稼ごうとしていないものを手に入れるのを助けるだけではないことを私たちに納得させるのに間違いなく役立ちます。:)
sarnold 2012年

4
@AlexLockwood私が質問を最初に投稿したとき、私は質問に「宿題」というタグを付けると、(「宿題」タグの状態の説明のように)問題を解決するのに役立つ手がかりを提供するよう求められ、答えを出すだけではありません。それが私が問題の質問をはっきりと尋ねた理由です:)
Steve

回答:


237

矛盾があるため、次のようなxものy(mod 2 n)がいくつか存在すると仮定します。

~(x+y) == ~x + ~y

2の補数*により、

      -x == ~x + 1
<==>  -1 == ~x + x

この結果に注目して、

      ~(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

したがって、矛盾。したがって、~(x+y) != ~x + ~yすべてのxand y(mod 2 n)についてです。


*興味深いのは、1の補数演算を備えたマシンでは、等式は実際にはすべてのxおよびに当てはまるということですy。これは、補数の下にあるため~x = -xです。したがって、~x + ~y == -x + -y == -(x+y) == ~(x+y)


47
もちろん、Cはこの動作を必要としません。2の補数表現を必要としないため。
Billy ONeal

12
ところで、平等である真の 1の補数のために。NOT演算は一般に実際には数値に対して定義されていないため、NOTと加算を混在させると、数値の表現に応じて動作が異なります。
nhahtdh、2012年

9
問題を符号なし整数であると言い換えると、2の補数はまったく機能しません。
R .. GitHub ICEのヘルプを停止する'20

5
さらにシンプルに、私見: ~x == -(x+1)~(x+y) == ~x + ~y-(x+y+1) == -(x+1) + -(y+1)-1 == -2
つまり

7
@BillyONeal、心配しないでください、私は冗談でした、そしてあなたがそれを言ったことを感謝します:) 補数演算を行う機械に出会ったその日に飲み物を買ってあげる…どうだい?ハハ
アレックスロックウッド

113

2の補数

上の広大な場合は、コンピュータの大多数、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)、常にfalseです。


とは言っても、Cは2の補数を必要としないことをペダントは指摘するので、我々も考慮しなければなりません...

自分の補数

1の補数-x単にとして表現されます~x。ゼロはすべて0の(+0)とすべて1の(-0)の両方の表現を持つ特殊なケースですが、IIRC、Cでは+0 == -0ビットパターンが異なっていても必要なので、これは問題になりません。で置き換え~てください-

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

これは真のすべてのためにxy


13
+1は、実際に2の補数と1の補数の両方を同等に考慮した回答です。
CVn '20年

13
@ dan04 、+0 == -0. 最後に、Cで意味のあるもの:)
Alex Lockwood

32

両方の唯一の右端のビットを考えるxy(IE場合。x == 13これは1101ベース2に、我々は唯一の、最後のビットを見ていきます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:

これもあなたにお任せします。

可能な入力が与えられた場合、方程式の左辺と右辺では常に右端のビットが異なることを示すことができるため、少なくとも1つのビットが反転しているため、両側が等しくないことが証明されます。互いに。


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.

さて、

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

したがって、それらは常に不等となり、1の違いがあります。


4
@nhahtdhと、~固定されていない幅の数値に対する操作をどのように定義しますか?
hamstergene 2012年

1
私はこの答えをこれらのビット数で示したので、クラスで教えられたものと簡単に関連付けることができます。〜xは、数を表すために使用されるビット数nに大きく依存することに注意してください。したがって、これを実験的に検証しようとする場合は、1つに固執するのが賢明です。
Karthik Ku​​mar Viswanathan 2012年

1
@hamstergene:私はビット数が固定されていることを知っていますが、私のポイントは、それらの量(8、16など)である必要はないということです。
nhahtdh 2012年

1
これらは、答えを検証するプログラムを簡単に作成できる値です。〜xと〜yが与えられたものと一致するように書かれている限り、どのnでも機能します。
Karthik Ku​​mar Viswanathan 2012年

1
@hamstergene:私は証明に問題はありませんが、数字がそれらの場合にのみ機能するという誤った意味を与えているだけです。
nhahtdh 2012年

27

ヒント:

x + ~x = -1(mod 2 n

質問の目的が数学のテスト(C仕様の読み取りスキルではなく)であると仮定すると、これで答えが得られます。


2
2の補数マシンのみ。(C標準では必要ありません)
Billy ONeal

12
@ビリー:それは「両腕の人だけのために」と言っているようなものです。
dan04

2
@ dan04:いいえ、そうではありません。私はすべての署名されたマグニチュードとそれを補う表現が世界からなくなったと言いたいです。しかし、私はそれを言うのは間違っているでしょう。C標準では、この仮定を行うことはできません。したがって、その仮定を行うコードは、ほとんどの場合悪いコードです。(特に、ビットいじるよりも通常、符号付き数値をいじる方法が優れている場合、特に、ほとんどの場合、符号なし数値がおそらくほとんどの場合に適しています)
Billy ONeal

10

1と2の補数(さらには42の補数)でも、これは証明できます。

~x + ~y == ~(x + a) + ~(y - a)

さてa = y、私たちは持っています:

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

または:

~x + ~y == ~(x + y) + ~0

したがって、2の補数で~0 = -1は、命題は誤りです。

それを補完するもの~0 = 0として、命題は真実です。


7

Dennis Ritchieの本によると、Cはデフォルトで2の補数を実装していません。したがって、あなたの質問は必ずしも正しいとは限りません。


5

MAX_INT表されるintとする011111...111(ただし、多くのビットがある場合)。そして、あなたはそれを知っている、~x + x = MAX_INTそして~y + y = MAX_INTそのため、あなたは確かに間の違いを知っているだろう、~x + ~y~(x + y)あります1


5

Cは、2の補数が実装されているものである必要はありません。ただし、符号なし整数については、同様のロジックが適用されます。このロジックでは、差異は常に1になります。


3

もちろん、Cは2の補数表現を必要としないため、この動作を必要としません。たとえば、~x = (2^n - 1) - x~y = (2^n - 1) - yはこの結果を取得します。


0

ああ、基本的な離散数学!

ドモルガンの法則を確認する

~x & ~y == ~(x | y)

~x | ~y == ~(x & y)

ブール証明にとって非常に重要です!


正解です。C +は加算であり、*乗算であり、ブールorまたはandではありません。
nalply

nalply、誤った演算子を指摘していただきありがとうございます。これは正しい演算子で更新されましたが、元の質問には適用されないという点で正しいです。
David Kaczynski

1
まあ、trueが1でfalseがゼロの場合、+と*はorとまったく同じように動作し、さらに2の補数は動作しないため、法則が適用されます。
a1an 2012年

指摘してくれてありがとう、a1an。デモーガンの法則が元の質問にどのように適用できるかを考えていましたが、Cプログラミングまたは離散数学のどちらかを勉強してから数年になります。
David Kaczynski
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.