~ x + ~ y == ~ (x + y) всегда ложно?

153

Этот код всегда оценивается как ложный? Обе переменные являются двумя знаковыми дополнениями.

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

Я чувствую, что должно быть какое-то число, которое удовлетворяет условиям. Я пытался проверить числа между, но так -5000и 5000не достиг равенства. Есть ли способ установить уравнение, чтобы найти решение для условия?

Будет ли замена одного на другой причиной коварной ошибки в моей программе?

Стив
источник
6
Вы хотите доказать или что-то?
Элвин Вонг
26
Помните, что в случаях целочисленного переполнения со знаком это технически неопределенное поведение. Таким образом, он может вернуться, trueдаже если они никогда не будут принимать строгое дополнение к двум.
Мистика
1
@AlvinWong да объяснение было бы хорошо
Стив
1
@ Steve: Вы можете продемонстрировать, что вы попробовали все обычные подозреваемые (-1, 0, 1, 2 и т. Д.) Во всех комбинациях, а также свои попытки «решить» проблему для небольших размеров слова ( три бита - четыре бита?). Это определенно помогло бы убедить нас в том, что мы не просто помогаем кому-то получить то, что он сначала не пытался заработать для себя. :)
sarnold
4
@AlexLockwood Когда я впервые опубликовал вопрос, я предполагал пометить его как «домашнее задание» и попросить людей дать подсказки, чтобы помочь мне решить проблему (как описано в теге «домашнее задание»), а не просто дать ответы. Вот почему я просто задал вопрос проблемы :)
Steve

Ответы:

237

Предположим ради противоречия, что существуют некоторые xи некоторые y(mod 2 n ) такие, что

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

В дополнение к двум * мы знаем, что

      -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для всех xи y(мод 2 н ).


* Интересно отметить, что на машине с арифметикой дополнения равенство действительно справедливо для всех xи y. Это потому, что под чьим-то дополнением ~x = -x. Таким образом, ~x + ~y == -x + -y == -(x+y) == ~(x+y).

Алекс Локвуд
источник
47
Конечно, C не требует такого поведения; поскольку это не требует представления дополнения до двух.
Билли ONEAL
12
Кстати, равенство верно для своего дополнения. Операция NOT на самом деле не определена для числа, поэтому смешивание NOT с сложением приводит к различному поведению в зависимости от представления числа.
nhahtdh
9
Можно было бы просто переформулировать проблему для целых чисел без знака, и тогда дополнение к двум не входит в игру вообще.
R .. GitHub ОСТАНОВИТЬСЯ, ПОМОГАЯ ЛЬДУ
5
Еще проще, ИМХО ~x == -(x+1), так ~(x+y) == ~x + ~yподразумевает, -(x+y+1) == -(x+1) + -(y+1)подразумевает-1 == -2
BlueRaja - Дэнни Пфлюгофт
7
@BillyONeal, не волнуйся, я только пошутил, и я ценю, что ты упомянул об этом :). Я куплю тебе напиток в тот день, когда я столкнусь с машиной, которая выполняет арифметику своего дополнения ... как это звучит? хаха
Алекс Локвуд
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's ( +0), так и all-1's ( -0), но IIRC, C требует, +0 == -0даже если они имеют разные битовые комбинации, так что это не должно быть проблемой. Просто заменить ~с -.

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

что верно для всех xи y.

dan04
источник
13
+1 за ответ, который фактически учитывает как дополнение двух, так и дополнение одного на равной основе.
CVn
13
@ dan04, +0 == -0. Наконец то, что имеет смысл в C. :)
Алекс Локвуд
32

Рассмотрим только самый правый бит обоих xи y(т.е. если он x == 13находится 1101в базе 2, мы рассмотрим только последний бит, а 1) Тогда есть четыре возможных случая:

х = 0, у = 0:

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

х = 0, у = 1:

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

х = 1, у = 0:

Я оставлю это на ваше усмотрение, так как это домашняя работа (подсказка: она такая же, как и предыдущая с заменой x и 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 а как вы определяете ~работу с нефиксированными числами ширины?
хомяк
1
Я дал этот ответ с таким количеством битов, чтобы было легко соотнести его с тем, что преподается на уроках. Обратите внимание, что ~ x сильно зависит от количества бит n, используемых для представления числа. Поэтому разумно придерживаться одного, пытаясь проверить это экспериментально.
Картик Кумар Вишванатан
1
@hamstergene: я знаю, что число битов фиксировано, но я хочу сказать, что это не должно быть то количество (8, 16 и т. д.).
nhahtdh
1
Это те значения, для которых легко написать программу для проверки ответа. Он работает для любого n, если ~ x и ~ y написаны так, чтобы соответствовать заданному.
Картик Кумар Вишванатан
1
@hamstergene: у меня нет проблем с доказательством, просто цифры дают ложное следствие того, что это работает только для тех случаев.
nhahtdh
27

Подсказка:

x + ~x = -1(мод 2 н )

Предполагая, что целью этого вопроса является проверка вашей математики (а не навыков чтения спецификаций), вы должны получить ответ.

user541686
источник
2
Только на двух дополняющих машинах. (Стандарт C не требует этого)
Билли ONeal
12
@ Билли: Это все равно что сказать "только для двухруких людей".
dan04
2
@ Dan04: Нет, это не так. Я хотел бы сказать, что все подписанные величины и дополняющие их представления исчезли из мира. Но я был бы неправ, говоря это. Стандарт C не позволяет вам делать такое предположение; поэтому я бы сказал, что код, который делает это предположение, является плохим кодом большую часть времени. (Особенно, когда обычно есть лучшие способы связываться со знаковыми числами, чем битовое чередование; и особенно когда неподписанные числа, вероятно, в большинстве случаев являются лучшим выбором в любом случае)
Billy ONeal
10

Это можно доказать как в одном, так и в двух (и даже в 42-х годах):

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

Теперь позвольте a = yи мы имеем:

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

или:

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

Следовательно, в дополнение к этому ~0 = -1, утверждение неверно.

В дополнение к этому ~0 = 0, утверждение верно.

ypercubeᵀᴹ
источник
7

Согласно книге Денниса Ритчи, Си не реализует дополнение двух по умолчанию. Поэтому ваш вопрос не всегда может быть правдой.

user1457474
источник
5

Позвольте MAX_INTбыть int, представленный как 011111...111(для скольких битов не существует). Тогда вы это знаете, ~x + x = MAX_INTи ~y + y = MAX_INT, следовательно, поэтому вы наверняка будете знать, что разница между ~x + ~yи ~(x + y)есть 1.

Адриан Монах
источник
5

С не требует, чтобы два дополнения были тем, что реализовано. Однако для целого числа без знака применяется аналогичная логика. Различия всегда будут 1 по этой логике!

user1422551
источник
3

Конечно, C не требует такого поведения, потому что не требует представления дополнения до двух. Например, ~x = (2^n - 1) - x& ~y = (2^n - 1) - yполучит этот результат.

user1472392
источник
0

Ах, фундаментальная дискретная математика!

Проверьте закон де Моргана

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

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

Очень важно для логических доказательств!

Давид Качиньский
источник
Просто неправильно. В C + есть сложение, * умножение, а не логическое или или и и.
Вскоре
Спасибо, что указали на неправильные операторы, вежливо. Теперь в него были добавлены правильные операторы, хотя вы правы в том, что это не относится к исходному вопросу.
Давид Качиньский
1
Что ж, если true равно единице, а false равно нулю, тогда + и * ведут себя точно так же, как и, и, кроме того, дополнение к двум ведет себя так, как будто нет, поэтому закон, тем не менее, применяется.
A1An
Спасибо за указание на это, a1an. Я пытался придумать, как законы Де Моргана все еще могут быть применимы к исходному вопросу, но прошло несколько лет с тех пор, как я изучал или программирование на С, или дискретную математику.
Давид Качиньский