确定一个点的象限

时间:2012-03-15 10:41:00

标签: 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;
        }

5 个答案:

答案 0 :(得分: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) ]

当你考虑你想要的结果时

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

您可以使用公式

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

所以在Java

y = (y>>>31);
return ((x>>>31) ^ y) + y + y + 1;

编辑仅针对那些对内联汇编感到好奇的人......

;; 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

答案 1 :(得分:4)

这是给你的方法。看起来很简单......

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

答案 2 :(得分: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];

答案 3 :(得分:0)

保持简单!不需要分支,bit-twiddling,内存查找,汇编语言或其他复杂功能。

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)

然后如果你收集术语并简化,你会得到我用过的表达式。)

答案 4 :(得分: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]);
}