确定一个点的象限

sgo*_*owd 6 java performance geometry

我需要以更快的方式确定点的象限.我只知道"确定使用标志"的方法.我正在寻找一个好的方法,如果有的话.如果没有任何修复我的代码会有所帮助.假设飞机上有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;
        }
Run Code Online (Sandbox Code Playgroud)

Lou*_*cci 5

在对一段代码进行微优化时,要避免分支和内存查找.使用内联汇编,您可以使用CMOV(条件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) ]
Run Code Online (Sandbox Code Playgroud)

当你考虑你所追求的结果时

x.sign y.sign Quad
0      0      1
0      1      4
1      0      2
1      1      3
Run Code Online (Sandbox Code Playgroud)

你可以得到公式

(x.sign XOR y.sign + y.sign + y.sign) + 1
Run Code Online (Sandbox Code Playgroud)

所以在Java中

y = (y>>>31);
return ((x>>>31) ^ y) + y + y + 1;
Run Code Online (Sandbox Code Playgroud)

编辑只为那些对内联汇编感到好奇的人...

;; 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
Run Code Online (Sandbox Code Playgroud)