Как программно вернуть максимум два целых числа без использования каких-либо операторов сравнения и без использования if
, else
и т.д.
Как программно вернуть максимум двух целых чисел без использования каких-либо операторов сравнения и без использования if, else и т.д.?
Ответ 1
max://Поместим MAX (a, b) в
a -= b;
a &= (~a) >> 31;
a += b;
и
int a, b;
min://Поместим MIN (a, b) в
a -= b;
a &= a >> 31;
a += b;
из здесь.
Ответ 2
http://www.graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
r = x - ((x - y) & -(x < y)); // max(x, y)
Вы можете получать удовольствие от арифметического смещения (x - y)
, чтобы насытить бит знака, но этого обычно достаточно. Или вы можете проверить высокий бит, всегда весело.
Ответ 3
Я думаю, что у меня есть.
int data[2] = {a,b};
int c = a - b;
return data[(int)((c & 0x80000000) >> 31)];
Неужели это не сработает? В принципе, вы принимаете разницу между двумя, а затем возвращаете то или другое на основе знакового бита. (Так как процессор делает больше или меньше, чем в любом случае.) Поэтому, если знаковый бит равен 0, верните a, так как a больше или равно b. Если знаковый бит равен 1, верните b, потому что вычитание b из a вызвало отрицательный результат, указывающий, что b больше, чем a. Просто убедитесь, что ваши ints подписаны на 32 бита.
Ответ 4
В математическом мире:
max(a+b) = ( (a+b) + |(a-b)| ) / 2
min(a-b) = ( (a+b) - |(a-b)| ) / 2
Помимо математической корректности, это не делает предположения о размере бита, поскольку необходимо выполнить операции переключения.
|x|
означает абсолютное значение x.
Комментарий:
Вы правы, абсолютная ценность была забыта. Это должно быть справедливо для всех a, b положительных или отрицательных
Ответ 5
return (a > b? a: b);
или
int max(int a, int b)
{
int x = (a - b) >> 31;
int y = ~x;
return (y & a) | (x & b);
}
Ответ 6
не так злобно, как выше... но...
int getMax(int a, int b)
{
for(int i=0; (i<a) || (i<b); i++) { }
return i;
}
Ответ 7
Так как это головоломка, решение будет слегка запутанным:
let greater x y = signum (1+signum (x-y))
let max a b = (greater a b)*a + (greater b a)*b
Это Haskell, но он будет таким же на любом другом языке. C/С# люди должны использовать "sgn" (или "sign"?) Вместо signum.
Обратите внимание, что это будет работать на ints произвольного размера и на reals также.
Ответ 8
Из z0mbie (знаменитый писатель-писатель) статья "Полиморфные игры", может быть, вы сочтете это полезным:
#define H0(x) (((signed)(x)) >> (sizeof((signed)(x))*8-1))
#define H1(a,b) H0((a)-(b))
#define MIN1(a,b) ((a)+(H1(b,a) & ((b)-(a))))
#define MIN2(a,b) ((a)-(H1(b,a) & ((a)-(b))))
#define MIN3(a,b) ((b)-(H1(a,b) & ((b)-(a))))
#define MIN4(a,b) ((b)+(H1(a,b) & ((a)-(b))))
//#define MIN5(a,b) ((a)<(b)?(a):(b))
//#define MIN6(a,b) ((a)>(b)?(b):(a))
//#define MIN7(a,b) ((b)>(a)?(a):(b))
//#define MIN8(a,b) ((b)<(a)?(b):(a))
#define MAX1(a,b) ((a)+(H1(a,b) & ((b)-(a))))
#define MAX2(a,b) ((a)-(H1(a,b) & ((a)-(b))))
#define MAX3(a,b) ((b)-(H1(b,a) & ((b)-(a))))
#define MAX4(a,b) ((b)+(H1(b,a) & ((a)-(b))))
//#define MAX5(a,b) ((a)<(b)?(b):(a))
//#define MAX6(a,b) ((a)>(b)?(a):(b))
//#define MAX7(a,b) ((b)>(a)?(b):(a))
//#define MAX8(a,b) ((b)<(a)?(a):(b))
#define ABS1(a) (((a)^H0(a))-H0(a))
//#define ABS2(a) ((a)>0?(a):-(a))
//#define ABS3(a) ((a)>=0?(a):-(a))
//#define ABS4(a) ((a)<0?-(a):(a))
//#define ABS5(a) ((a)<=0?-(a):(a))
веселит
Ответ 9
Это своего рода обман, используя ассемблерный язык, но он тем не менее интересен:
// GCC inline assembly
int max(int a, int b)
{
__asm__("movl %0, %%eax\n\t" // %eax = a
"cmpl %%eax, %1\n\t" // compare a to b
"cmovg %1, %%eax" // %eax = b if b>a
:: "r"(a), "r"(b));
}
Если вы хотите быть строгим в отношении правил и сказать, что инструкция cmpl
является незаконной для этого, тогда будет работать следующая (менее эффективная) последовательность:
int max(int a, int b)
{
__asm__("movl %0, %%eax\n\t"
"subl %1, %%eax\n\t"
"cmovge %0, %%eax\n\t"
"cmovl %1, %%eax"
:: "r"(a), "r"(b)
:"%eax");
}
Ответ 10
int max(int a, int b)
{
return ((a - b) >> 31) ? b : a;
}