[Я знаю, что это на самом деле старое, но у меня был тот же вопрос, и так как верхние ответы были противоречивыми ...]
поразрядным комплимент действительно дистрибутивным более того. Проблема вашего кода (и рода Каганара, но неправильный ответ) заключается в том, что вы бросаете биты переноса - вы можете сделать это в двух комплиментах, но не в своем комплименте.
Все, что вы используете для хранения суммы, требует большего объема памяти, чем то, что вы суммируете, чтобы не уронить бит переноса. Затем сверните биты переноса обратно в число бит, которое вы используете, чтобы сохранить ваши операнды, чтобы получить правильную сумму. Это называется «концевой перенос» в арифметике комплимента.
Из статьи Википедии (https://en.wikipedia.org/wiki/Signed_number_representations#Ones «_complement):
Чтобы сложить два числа, представленные в этой системе, один делает обычный двоичный дополнение, но в этом случае необходимо сделать конец вокруг нести: это , добавьте любой результат переноса в итоговую сумму. Чтобы понять, почему это необходимо, рассмотрим следующий пример, показывающий случай добавления -1 (11111110) до +2 (00000010):
binary decimal
11111110 –1
+ 00000010 +2
─────────── ──
1 00000000 0 ← Not the correct answer
1 +1 ← Add carry
─────────── ──
00000001 1 ← Correct answer
В предыдущем примере, первый двоичный сложение дает 00000000, что неверно. Правильный результат (00000001) появляется только в том случае, когда перенос добавлен обратно.
Я немного изменил код, чтобы облегчить выполнение самой математики для проверки и проверки работоспособности. Это может потребовать немного больше мысли с использованием целочисленных типов данных со знаком или для учета заимствований за границей вместо их переноса. Я не зашел так далеко, так как мое приложение касается контрольных сумм (т. Е. Без знака и только для добавления).
unsigned short n1 = 5; //using 16-bit unsigned integers
unsigned short n2 = 3;
unsigned long oc_added = (unsigned short)~n1 + (unsigned short)~n2; //32bit
/* Fold the carry bits into 16 bits */
while (oc_added >> 16)
oc_added = (oc_added & 0xffff) + (oc_added >> 16);
unsigned long oc_sum = ~(n1 + n2); //oc_sum has 32 bits (room for carry)
/* Fold the carry bits into 16 bits */
while (oc_sum >> 16)
oc_sum = (oc_sum & 0xffff) + (oc_sum >> 16);
int result = oc_added == oc_sum;
unsigned short calc = ~n1;
unsigned short calc0 = ~n2;
unsigned short calc1 = ~n1 + ~n2; //loses a carry bit
unsigned short calc2 = ~(n1 + n2);
printf("(Part B: n1 is %d, n2 is %d\n", n1, n2);
printf("Part B: (calc is: %d and calc0 is: %d\n", calc, calc0);
printf("Part B: (calc1 is: %d and calc2 is: %d\n", calc1, calc2);
printf("Part B: (~%d + ~%d) == ~(%d + %d) evaluates to %d\n", n1, n2, n1, n2, result);
Это не похоже на распределительное правило. И распространять что над чем? – nhahtdh
Тогда, возможно, дистрибутив - это не правильное слово? Мне просто интересно, можно ли доказать неравенство. То есть, является ли сумма дополнений к 2 числам, равным числу, дополняющему сумму? – user1317750
Что означает '+'? Это ИЛИ, или это ДОБАВИТЬ? – nhahtdh