2012-03-15 7 views
6

ポイントの象限をより速く決定する必要があります。私は「標識の使用を決定する」方法のみを認識しています。私は良いアプローチがあればそれを探しています。私のコードに修正がない場合は助けになります。平面に4つの四角形があると仮定します。私のコードポイントの象限の決定

 int x = scan.nextInt() > 0 ? 1 : 0; 
     int y = scan.nextInt() > 0 ? 1 : 0; 
     switch (x) { 
     case 1: 
      switch (y) { 
      case 1: 
       quad = 1; 
       break; 
      case 0: 
       quad = 4; 
       break; 
      } 
      break; 

     case 0: 
      switch (y) { 
      case 1: 
       quad = 2; 
       break; 
      case 0: 
       quad = 3; 
       break; 
      } 
      break; 
     } 
+0

この宿題はありますか? 「符号を使用して判断する」アルゴリズムを実装しましたか?それにパフォーマンスの問題はありますか(それはなぜ十分速くないのですか?)。あなたのコードを私たちに教えてください。 – Jesper

+0

@Jesper宿題ではありません。私のコードを貼り付けた。 – sgowd

+0

だから、なぜそれは十分に速くないのですか? – Jesper

答えて

4

枝とメモリのルックアップは、コードのスニペットにマイクロ最適化を行う際に避けるべき事です。インラインアセンブリでは、CMOV(Conditional MOV)を使用してx86システムの速度を上げることができます。 Javaのホットスポットコンパイラは、この命令を使用することにも使用できます。しかし、スニペットはとてもシンプルなので、分岐やメモリのルックアップを避けるためにあまりにも多くの操作を行うと(最終的に)敗者になる可能性があります。

static int[] QUAD_LUT = new int[]{1, 2, 4, 3}; 
... 
// use the sign bit on the integers 
return QUAD_LUT[ (x >> 31) | ((y >> 30) & 0x2) ] 

あなたはその結果について考えるとき、あなたはしている

x.sign y.sign Quad 
0  0  1 
0  1  4 
1  0  2 
1  1  3 

あなたが式

y = y>>31; 
return ((x>>31)^y) + y + y + 1; 
のJava
でそう

(x.sign XOR y.sign + y.sign + y.sign) + 1 

を得ることができた後、 10

EDITただ、インラインアセンブリについて興味の人々のために...

;; NASM/FASM syntax 
;; GetQuadrant(int x, int y) 
;; RETURN [1|2|3|4] in EAX register 
GetQuadrant: 
    MOV  eax, [esp+4] ;; = x 
    MOV  ecx, [esp+8] ;; = y 
    SHR  eax, 31 ;; = >> 31 
    SHR  ecx, 31 ;; = >> 31 
    XOR  eax, ecx ;; = x XOR y 
    LEA  eax, [eax + ecx * 2 + 1] ;; = x + y*2 + 1 
    RET  8 ;; correct stack and return 
+0

おめでとう、おめでとう! – PhyBandit

+0

いいです。私はこれらの演算子の考えを得ていませんでした。 – sgowd

4

あなたのための方法です。シンプルなルックス...

getQuadrant(int x, int y) { 
    if (x >= 0) { 
     return y >= 0 ? 1 : 4; 
    } else { 
     return y >= 0 ? 2 : 3; 
    } 
} 
+0

それは私のものよりも単純なものです。しかし、より速いものではありません。 – sgowd

+0

目標がパフォーマンスの場合、この回答は正しくありません。ブランチングはパフォーマンス上の障害として知られています。目標がベストプラクティス/明快ならば、これは明らかな勝者です。 –

1
int[] quads = new int[] { 3, 2, 4, 1 }; 

int x = scan.nextInt() > 0 ? 2 : 0; 
int y = scan.nextInt() > 0 ? 1 : 0; 

int result = quads[x + y]; 
+0

パフォーマンス賢明なこれは、2つのブランチを使用して、メモリのルックアップです。静的な "クワッド"ルックアップを持つブランチレスバージョンを使用すると、最適化の一般的な選択肢になるでしょう。 –

0

それをシンプルに保ちます!ブランチ、ビットツイリング、メモリルックアップ、アセンブリ言語、その他の複雑さは必要ありません。

int getQuadrant(int x, int y) { 
    int X = (x >= 0); 
    int Y = (y >= 0); 
    return 3 + X - Y - 2 * X * Y; 
} 

説明私の機能のようにXYを考えると、象限は、この二次多項式で与えられます。

1 * X * Y + 2 * (1 - X) * Y + 3 * (1 - X) * (1 - Y) + 4 * X * (1 - Y) 

、あなたが用語を収集し、簡素化した場合、その後、あなたが表現を取得します私は使用しました。)

+0

これはJAVAではありません。私はint X =(x> = 0)を初期化できません。この式はブール値を返すためです。 – sgowd

+0

ああ、そうです。私は、この種のことが、[Iversonの大会](http://en.wikipedia.org/wiki/Iverson_bracket)の利点を別のブール型で実証していると思います。 –

0

私は上記のビット回転の例を本当に気に入っていましたが、私は3dとCでこれを必要としました。誰かがそれを必要とするならば、これはJavaに変換するのに十分近いと確信しています。

int 
point_to_3d_quad (int x, int y, int z) 
{ 
    static int q[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 

    int X = (x >> ((sizeof(x)*8)-1)) & 1; 
    int Y = ((y >> ((sizeof(y)*8)-1)) & 1) << 1; 
    int Z = ((z >> ((sizeof(z)*8)-1)) & 1) << 2; 

    return (q[X | Y | Z]); 
} 
関連する問題