Побитовое насыщенное сложение в C (HW)

Я работаю над заданием, и я не могу понять, как это реализовать. Я должен сделать функцию sadd(int x, int y), которая возвращает числа, сложенные вместе, если только она не переполняется (тогда просто верните максимально возможное целое число). Мне удалось найти некоторые решения, включающие приведение типов и условные операторы, но они не разрешены в решении. Только операторы ~ ! ^ + << >> & и |.


person John C    schedule 11.03.2011    source источник
comment
Можно задавать вопросы по домашнему заданию, но вы должны пометить их как домашнее задание.   -  person Brian Roach    schedule 11.03.2011
comment
Попробуйте и опубликуйте, что у вас получилось. (Как сказал Брайан, вопросы HW — это хорошо, но лучше сделать все возможное и опубликовать свой код. Добро пожаловать в SO!)   -  person John    schedule 11.03.2011
comment
Без if/else это будет халтурно..   -  person Brendan Long    schedule 11.03.2011
comment
С ограниченным набором операций вы всегда можете найти решение...   -  person aaz    schedule 11.03.2011
comment
@Brendan: Подобные вопросы задаются, когда класс представляет собой компьютерную архитектуру или аналогичный продвинутый класс. Наборы инструкций низкого уровня имеют ограничения.   -  person John    schedule 11.03.2011


Ответы (2)


Для сложения чисел со знаком происходило переполнение, если вы складываете два числа одного знака и получаете результат с другим знаком. Из-за задействованных диапазонов невозможно создать переполнение при добавлении двух чисел с разными знаками.

Итак, что вы можете сделать, так это - наблюдая только за битом знака (самый значащий бит в дополнении до двух) - используйте исключающее ИЛИ, чтобы узнать, различаются ли два исходных числа по знаку, дополните это так, чтобы вы получили «0», если они были разными, «1» для одного и того же.

Затем вы можете использовать исключающее ИЛИ для результата по сравнению с одним из входных данных. Это даст «0», если они были одинаковыми, «1», если они были разными.

И эти два результата вместе, чтобы получить общий «1», если два входа были одинаковыми, но результат был другим, «0» в противном случае.

Затем вы можете использовать комбинацию сдвигов и операций ИЛИ, чтобы заполнить целое число этим значением. Предположим, вы находитесь в 32-битном целом, просто установите младшие 31 бит, чтобы получить положительное целое число с наибольшим значением. Затем вы можете сделать аналогичные наборы сдвигов и операций ИЛИ для бита знака любого из входов. Эксклюзивное ИЛИ результаты. Вместо этого это даст целое число с наименьшим значением, если входные данные были отрицательными.

РЕДАКТИРОВАТЬ: о, и используйте битовое значение того, было ли переполнение, расширенное, чтобы заполнить int, чтобы выбрать, какое значение вернуть, и соединив его с результатом, который вы бы вернули, если бы было переполнение, дополнив его и соединив его с нормальным аддитивный результат, затем объединение (или добавление) двух вместе.

Presto: вся бинарная логика, никаких условий. Я полагаю, поскольку это домашнее задание, вам не нужен настоящий код?


Девять лет спустя я согласен с комментарием @gman ниже; чтобы реализовать насыщающее сложение, используя только разрешенные операторы, вы должны полагаться на неопределенное поведение — и ответ выше неявно делает это.

Существенный риск при этом заключается в том, что компиляторы знают, какое поведение не определено, и могут использовать это во время оптимизации. Знаний о базовой архитектуре (например, о том, что это дополнение до двух, что он выполняет сдвиги со знаком) недостаточно, чтобы предсказать вывод компилятора.

Надежная производственная реализация возможна, но потребует условных операторов и, следовательно, не даст ответа на этот вопрос.

person Tommy    schedule 11.03.2011
comment
У меня это закодировано; не уверен, уместно ли добавлять полный исходный ответ на вопрос домашнего задания. Является ли объяснение, которое я дал, достаточно ясным? - person Tommy; 11.03.2011
comment
Вероятно, нет, но намекните ему на длину инструкций, которые занимает ваше решение (при условии, что набор инструкций MIPS). Можем поиграть в код-гольф ;-) - person smci; 28.08.2011
comment
Этот ответ неверен. Стандарт C, поскольку вопрос помечен c, является неопределенным поведением для подписанного переполнения. Я написал код, который проверял переполнение, проверяя изменение знака. Это не удалось, как только компилятор начал использовать тот факт, что переполнение не определено. - person gman; 05.07.2020
comment
@gman Вы верите, что можно написать насыщающее добавление, используя только операторы, указанные в вопросе, и не полагаясь на неопределенное поведение? В этом разница между изменением ответа на «вам придется полагаться на неопределенное поведение» или просто его удалением. - person Tommy; 05.07.2020
comment
Из всего, что я прочитал, я предполагаю, что ответ - нет, это невозможно, но, возможно, эксперт по C/C++ знает наверняка. - person gman; 05.07.2020

С веб-сайта 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;
}

Информационный центр ARM

person Wayne Taylor    schedule 26.04.2019