2010-03-16 2 views
4

Я хочу сделать простой макрос с #define для возврата меньшего из двух чисел.C Макро для минимум двух чисел

Как я могу это сделать в C? Предложите некоторые идеи и посмотрите, можете ли вы сделать ее еще более запутанной.

+1

Возможный дубликат [MIN и MAX in C] (http://stackoverflow.com/questions/3437404/min-and-max-in-c) – Antonio

ответ

-6

Для немного запутанным, попробуйте следующее:

#define MIN(a,b) ((((a)-(b))&0x80000000) >> 31)? (a) : (b) 

В основном, это вычитает их, и смотрит на знак-бит, как 1-или-0. Если вычитание приводит к отрицательному числу, первый параметр меньше.

+7

Предполагая, что тип 32-бит. – GManNickG

+0

Спасибо - это то, что я искал. – VaioIsBorn

+2

К сожалению, на самом деле это не работает даже для 32-битных целых чисел, если вы не считаете, что 2147483647 меньше -1. –

11

правило:

#define min(a, b) (((a) < (b)) ? (a) : (b)) 

Имейте в виду, это оценивает минимум в два раза, что стало причиной катастрофы в recent question.

Но почему вы хотите запутать его?


Это хранит результат в переменной и оценивает каждый аргумент только один раз. Это в основном бедных мужчин встроенная функция + декларация:

#define min(t, x, a, b) \ 
      t x; \ 
      { \ 
       t _this_is_a_unique_name_dont_use_it_plz_0_ = a; \ 
       t _this_is_a_unique_name_dont_use_it_plz_1_ = b; \ 
       x = _this_is_a_unique_name_dont_use_it_plz_0_ < \ 
        _this_is_a_unique_name_dont_use_it_plz_1_ ? \ 
        _this_is_a_unique_name_dont_use_it_plz_0_ : \ 
        _this_is_a_unique_name_dont_use_it_plz_1_ ; \ 
      } 

использовать его как:

min(int, x, 3, 4) 
/* x is an int, equal to 3 
    Just like doing: 

    int x = min(3, 4); 

    Without double evaluation. 
*/ 
+0

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

+0

Руководитель, на каком языке? Если мы отправимся на C++, я уверен, что могу попытаться дать ему что-нибудь, чтобы пожарить его экспертную лапшу. Но хорошо, какие предположения мы можем сделать? Являются ли эти целые числа минимальными? Опять же, возможно, это всего лишь предыстория, чтобы обмануть меня в ответ. :) – GManNickG

+0

«Я могу дать ему что-нибудь, чтобы пожарить его экспертную лапшу» - рад это слышать, ожидая дальнейших ответов xD. Кстати, вопрос был в том, что в классе нам нужна простая минимальная функция, поэтому я решил пойти с макросом, чтобы он выглядел больше c-ish. – VaioIsBorn

3

Конечно, вы можете использовать #define для этого, но почему вы хотите? Проблема с использованием #define, даже с круглыми скобками, заключается в том, что вы получаете неожиданные результаты с таким кодом (хорошо, вы на самом деле этого не делали, но это иллюстрирует проблему).

int result = min(a++, b++); 

Если вы используете C++ не C, конечно же, лучше использовать функцию инлайн, которая (I) избегает оценки параметров более чем один раз, и (б) типобезопасен (вы можете даже представить версии с другие типы значений, например unsigned, double или string).

inline int min(int a, int b) { return (a < b) ? a : b; } 
+2

В C++ это должна быть функция шаблона для * любого * типа. И, конечно, нет необходимости переписывать его; есть уже один в ''. – GManNickG

+1

Вы можете написать встроенную функцию в C99 или с расширениями компилятора ('__inline' в MSVC,' __inline__' в GNU C89). –

4

И, только для ада этого, пример GNU C:

#define MAX(a,b) ({ \ 
    typeof(a) _a_temp_; \ 
    typeof(b) _b_temp_; \ 
    _a_temp_ = (a); \ 
    _b_temp_ = (b); \ 
    _a_temp_ = _a_temp_ < _b_temp_ ? _b_temp_ : _a_temp_; \ 
    }) 

Это не затемненные, но я думаю, что это работает для любого типа, в любом контексте, (почти см комментариев) любой аргументы и т. д .; пожалуйста, исправьте, если вы можете думать о каких-либо контрпримерах.

+1

Это вряд ли произойдет, но это будет нарушено, если 'a' или' b' станут самими переменными с именем '_a_temp_' и' _b_temp_'. – jamesdlin

+0

Да, я думал о склеивании на '__LINE__', но это не стоило усилий; если бы существовал только макрос '__UNIQUE__' ... –

+0

Вы бы заслужили гораздо лучший результат, см. http://stackoverflow.com/a/3437484/2436175 Возможно, что пропустил немного объяснение причины, по которой этот безопаснее. – Antonio

3

Я думаю, что этот метод довольно мило:

#define min(a, b) (((a) + (b) - fabs((a) - (b))) * 0.5)

0

Если бы я просто пытался слегка запутать это, я бы, вероятно, пойти что-то вроде:

#define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0)) 

Я думаю, что решение Doynax является симпатичный, тоже. Обычные резервирования для обоих аргументов макроса оцениваются более одного раза.

0

Я хочу создать простой макрос с #define для возврата меньшего из двух чисел.

Я хотел бы добавить решение, когда числа являются с плавающей точкой.


Рассмотрим, когда числа с плавающей запятой и один из чисел not-a-number. Тогда результат a < b всегда равен false независимо от значения другого номера.

// the result is `b` when either a or b is NaN 
#define min(a, b) (((a) < (b)) ? (a) : (b)) 

Может быть желательно, чтобы результат был следующим, где «аргументы NaN обрабатываются как отсутствующие данные». C11 Сноска # 242

a NaN | b NaN | a < b | min 
-------+---------+---------+--------------- 
No  | No  | No  | b 
No  | No  | Yes | a 
No  | Yes | .  | a 
Yes | No  | .  | b 
Yes | Yes | .  | either a or b 

Чтобы сделать это с помощью макроса в C будет просто обертка функция fmin() которая supprts приведенную выше таблицу. Конечно, код обычно должен использовать функцию fmin().

#include <math.h> 
#define my_fmin(a, b) (fmin((a), (b)) 

Обратите внимание, что fmin(0.0, -0.0) может вернуться 0.0 или -0.0. Оба они имеют равное значение.