Я работаю над заданием, и я не могу понять, как это реализовать. Я должен сделать функцию sadd(int x, int y)
, которая возвращает числа, сложенные вместе, если только она не переполняется (тогда просто верните максимально возможное целое число). Мне удалось найти некоторые решения, включающие приведение типов и условные операторы, но они не разрешены в решении. Только операторы ~ ! ^ + << >> &
и |
.
Побитовое насыщенное сложение в C (HW)
Ответы (2)
Для сложения чисел со знаком происходило переполнение, если вы складываете два числа одного знака и получаете результат с другим знаком. Из-за задействованных диапазонов невозможно создать переполнение при добавлении двух чисел с разными знаками.
Итак, что вы можете сделать, так это - наблюдая только за битом знака (самый значащий бит в дополнении до двух) - используйте исключающее ИЛИ, чтобы узнать, различаются ли два исходных числа по знаку, дополните это так, чтобы вы получили «0», если они были разными, «1» для одного и того же.
Затем вы можете использовать исключающее ИЛИ для результата по сравнению с одним из входных данных. Это даст «0», если они были одинаковыми, «1», если они были разными.
И эти два результата вместе, чтобы получить общий «1», если два входа были одинаковыми, но результат был другим, «0» в противном случае.
Затем вы можете использовать комбинацию сдвигов и операций ИЛИ, чтобы заполнить целое число этим значением. Предположим, вы находитесь в 32-битном целом, просто установите младшие 31 бит, чтобы получить положительное целое число с наибольшим значением. Затем вы можете сделать аналогичные наборы сдвигов и операций ИЛИ для бита знака любого из входов. Эксклюзивное ИЛИ результаты. Вместо этого это даст целое число с наименьшим значением, если входные данные были отрицательными.
РЕДАКТИРОВАТЬ: о, и используйте битовое значение того, было ли переполнение, расширенное, чтобы заполнить int, чтобы выбрать, какое значение вернуть, и соединив его с результатом, который вы бы вернули, если бы было переполнение, дополнив его и соединив его с нормальным аддитивный результат, затем объединение (или добавление) двух вместе.
Presto: вся бинарная логика, никаких условий. Я полагаю, поскольку это домашнее задание, вам не нужен настоящий код?
Девять лет спустя я согласен с комментарием @gman ниже; чтобы реализовать насыщающее сложение, используя только разрешенные операторы, вы должны полагаться на неопределенное поведение — и ответ выше неявно делает это.
Существенный риск при этом заключается в том, что компиляторы знают, какое поведение не определено, и могут использовать это во время оптимизации. Знаний о базовой архитектуре (например, о том, что это дополнение до двух, что он выполняет сдвиги со знаком) недостаточно, чтобы предсказать вывод компилятора.
Надежная производственная реализация возможна, но потребует условных операторов и, следовательно, не даст ответа на этот вопрос.
С веб-сайта ARM о внутренних функциях:
4.1 Встроенные функции компилятора
Встроенные функции компилятора — это функции, предоставляемые компилятором. Они позволяют легко встраивать специфичные для предметной области операции в исходный код C и C++, не прибегая к сложным реализациям на языке ассемблера. Языки C и C++ подходят для решения широкого круга задач, но они не обеспечивают встроенной поддержки для конкретных областей применения, например, цифровой обработки сигналов (DSP). В пределах данного домена приложения обычно существует ряд операций, специфичных для домена, которые необходимо часто выполнять. Однако часто эти операции невозможно эффективно реализовать на C или C++. Типичным примером является насыщенное сложение двух 32-битных целых чисел в дополнении до двух со знаком, обычно используемое в программировании DSP. В следующем примере показана реализация операции насыщенного добавления на C.
#include <limits.h>
int L_add(const int a, const int b)
{
int c;
c = a + b;
if (((a ^ b) & INT_MIN) == 0)
{
if ((c ^ a) & INT_MIN)
{
c = (a < 0) ? INT_MIN : INT_MAX;
}
}
return c;
}
if
/else
это будет халтурно.. - person Brendan Long   schedule 11.03.2011