17

if比較演算子を使用せず、 、 などを使用せずに、最大 2 つの整数をプログラムで返すにはどうすればよいelseですか?

4

12 に答える 12

29

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;

ここから。

于 2008-10-22T20:27:26.957 に答える
8

http://www.graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax

r = x - ((x - y) & -(x < y)); // max(x, y)

算術シフト(x - y)を使って符号ビットを飽和させることもできますが、通常はこれで十分です。または、ハイビットをテストすることもできます。常に楽しいです。

于 2008-10-22T20:27:21.073 に答える
7

数学の世界では:

max(a+b) = ( (a+b) + |(a-b)| ) / 2
min(a-b) = ( (a+b) - |(a-b)| ) / 2

数学的に正しいことは別として、シフト操作が行う必要があるようにビットサイズについての仮定をしていません。

|x|xの絶対値を表します。

コメント:

そうです、絶対値を忘れてしまいました。これは、すべてのa、bの正または負に有効である必要があります

于 2009-05-15T08:44:26.853 に答える
6

私はそれを手に入れたと思います。

int data[2] = {a,b};
int c = a - b;
return data[(int)((c & 0x80000000) >> 31)];

これはうまくいきませんか?基本的に、2 つの差を取り、符号ビットに基づいてどちらかを返します。(これは、とにかくプロセッサがより大きいか小さいかを行う方法です。)したがって、符号ビットが 0 の場合、a は b 以上であるため、a を返します。符号ビットが 1 の場合、b を返します。これは、a から b を減算すると、結果が負になり、b が a より大きいことを示しているためです。int が 32 ビット署名されていることを確認してください。

于 2008-10-22T20:32:00.707 に答える
3

return (a > b ? a : b);

また

int max(int a, int b)
{
        int x = (a - b) >> 31;
        int y = ~x;
        return (y & a) | (x & b); 
}
于 2008-10-22T20:20:55.627 に答える
3

z0mbie (有名な virii ライター) の記事 "Polymorphic Games" から、役に立つかもしれません:

#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))

乾杯

于 2009-11-07T15:56:22.037 に答える
2

上記ほど派手ではありません...しかし...

int getMax(int a, int b)
{
    for(int i=0; (i<a) || (i<b); i++) { }
    return i;
}
于 2008-10-22T20:32:39.067 に答える
2

これはパズルなので、解決策は少し複雑になります。

let greater x y = signum (1+signum (x-y))

let max a b = (greater a b)*a + (greater b a)*b

これは Haskell ですが、他の言語でも同じです。C/C# のユーザーは、signum の代わりに「sgn」(または「sign」?) を使用する必要があります。

これは、任意のサイズの整数と実数でも機能することに注意してください。

于 2008-10-22T20:33:08.567 に答える
1

これは、アセンブリ言語を使用した一種の不正行為ですが、それでも興味深いものです。


// 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");
}
于 2008-10-22T20:43:24.270 に答える
1

これらの関数は比較を使用しますが、テストは使用せず、標準準拠のシステムで完全に定義されています。

int min(int a, int b) {
    return (a <= b) * a + (b < a) * b;
}
int max(int a, int b) {
    return (a <= b) * b + (b < a) * a;
}

これは、負の数に 2 の補数を使用するシステムに移植可能な、乗算のない代替手段です。

int min(int a, int b) {
    return (a & -(a <= b)) | (b & -(b < a));
}
int max(int a, int b) {
    return (b & -(a <= b)) | (a & -(b < a));
}

どちらのバージョンも、すべての整数型で機能します。

gccclangの両方が上記の関数に対してブランチレス コードを生成し、clangは両方の代替に対して同じ最適なコードを生成することに注意してください

于 2021-02-02T22:28:04.747 に答える