比較演算子やif、elseなどを使用せずに、最大2つの整数をプログラムで返すにはどうすればよいですか?
-
03-07-2019 - |
質問
比較演算子を使用せず、 if
、 else
などを使用せずに、プログラムで最大2つの整数を返すにはどうすればよいですか?
解決
max:// MAX(a、b)をaに入れます
a -= b;
a &= (~a) >> 31;
a += b;
そして:
int a、b;
min:// MIN(a、b)をaに入れます
a -= b;
a &= a >> 31;
a += b;
こちら。
他のヒント
http://www.graphics.stanford.edu/~seander /bithacks.html#IntegerMinOrMax
r = x - ((x - y) & -(x < y)); // max(x, y)
算術的にシフトして(x-y)
を楽しんで符号ビットを飽和させることができますが、通常はこれで十分です。または、常に楽しみながら上位ビットをテストできます。
手に入れたと思います。
int data[2] = {a,b};
int c = a - b;
return data[(int)((c & 0x80000000) >> 31)];
これは機能しませんか?基本的に、2つの差を取り、符号ビットに基づいてどちらかを返します。 (とにかく、プロセッサはこれを上回るまたは下回る方法を実行します。)したがって、符号ビットが0の場合、aはb以上であるため、aを返します。符号ビットが1の場合、aからbを引くと結果が負になり、bがaより大きいことを示すため、bを返します。 intが32ビットで署名されていることを確認してください。
数学の世界では:
max(a+b) = ( (a+b) + |(a-b)| ) / 2
min(a-b) = ( (a+b) - |(a-b)| ) / 2
数学的に正しいことは別として、シフト操作が行う必要があるため、ビットサイズについて仮定をしていません。
| x |
はxの絶対値を表します。
コメント:
あなたは正しい、絶対値は忘れられていた。これは、a、bのすべての正または負に対して有効でなければなりません
return(a&gt; b?a:b);
または
int max(int a, int b)
{
int x = (a - b) >> 31;
int y = ~x;
return (y & a) | (x & b);
}
上記ほどおしゃれではありませんが......
int getMax(int a, int b)
{
for(int i=0; (i<a) || (i<b); i++) { }
return i;
}
これはパズルであるため、ソリューションは少し複雑になります:
let greater x y = signum (1+signum (x-y))
let max a b = (greater a b)*a + (greater b a)*b
これはHaskellですが、他の言語でも同じです。 C / C#のユーザーは、「sgn」を使用する必要があります。 (またはsignumではなく&quot; sign&quot;?)。
これは、任意のサイズの整数および実数でも機能することに注意してください。
z0mbie(有名なviriiライター)の記事「多態性ゲーム」から、多分あなたはそれが役に立つとわかるでしょう:
#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))
歓声
これは一種の不正行為であり、アセンブリ言語を使用しますが、それでも興味深いものです:
// 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");
}
int max(int a, int b)
{
return ((a - b) >> 31) ? b : a;
}