2012-06-07 7 views
1

간단히 말하면, (x, y) 형태로 많은 점을가집니다.2D 평면에서 기하학적 점을 해시하는 방법은 무엇입니까?

나는 점은 키 인에 해시 테이블로 그 점을 넣고 싶다.

어떻게 클래스 PointhashCode() 메소드를 구현해야합니까? (당신이

public int hashCode() { 
    return x.hashCode()^y.hashCode(); 
} 

을이 테스트에 너무 많은 충돌을 제공하는 경우 : 나는 이중의 해시가 얼마나 잘 모르겠어요

class Point { 
    public double x; 
    public double y; 

    @Override 
    public int hashCode() { 
     // How do I implement here? 
    } 
} 
+0

@Cam : 나는 그것이 중복이라고 생각하지 않는다.그 대답은 어떻게 든 기하학적으로 가까운 점에 대해 동일한 해시를 만드는 무언가를 찾고 있습니다. –

+0

좋은 지적. 나는이 질문을 끝내기 위해 제 제안을 철회합니다. – Cam

+0

@OliCharlesworth 저에게 설명해 주셔서 감사합니다. 오늘 나는 이미 2 ~ 3 개의 질문을 마쳤습니다. 이 사람이 살아남기를 바랍니다. : D –

답변

2

숫자 평면 좌표에 가장 클러스터링하는 경향이있다; 왜냐하면 편안한 범위 내에서 숫자를 사용하는 경향이 있기 때문입니다. 이러한 이유 때문에 사소한 xor 조합은 바람직하지 않습니다. x == y이 충돌 할 모든 숫자와 마찬가지로 모든 숫자는 x + 1 == y 등입니다.

이러한 문제가 발생하지 않도록하기 위해, 나는 당신이 x 좌표를에 xor 전에 y 좌표의 바이트를 반대하는 것이 좋습니다. 이것은 한 입력의 가장 가변적 인 영역 (하위 바이트)과 다른 입력의 가장 작은 가변성 (상위 바이트)의 영역을 결합합니다. 이러한 알고리즘은 숫자 클러스터 (1에서 1000 사이의 x 값)를 고려할 때보다 균일 한 분포를 제공합니다.

해시 알고리즘은 무거운 클러스터링없이 숫자 필드를 생성 할 때 가장 잘 작동하므로 해시 충돌이 적어 해시 관련 데이터 구조가 더 빨라집니다. 다음

물론, 최적화되지이다, 그리고 확률은 아마 당신은 당신의 필요에 맞게 트리밍 할 수 있지만, 여기에 기본 생각이다 :

public int hashCode() { 

    long bits = Double.doubleToLongBits(y); 
    byte[] ybits = new byte[] { 
     (byte)((y >> 56) & 0xff), 
     (byte)((y >> 48) & 0xff), 
     (byte)((y >> 40) & 0xff), 
     (byte)((y >> 32) & 0xff), 
     (byte)((y >> 24) & 0xff), 
     (byte)((y >> 16) & 0xff), 
     (byte)((y >> 8) & 0xff), 
     (byte)((y >> 0) & 0xff), 
    }; 
    byte[] xbits = new byte[] { 
     (byte)((x >> 56) & 0xff), 
     (byte)((x >> 48) & 0xff), 
     (byte)((x >> 40) & 0xff), 
     (byte)((x >> 32) & 0xff), 
     (byte)((x >> 24) & 0xff), 
     (byte)((x >> 16) & 0xff), 
     (byte)((x >> 8) & 0xff), 
     (byte)((x >> 0) & 0xff), 
    }; 
    // this combines the bytes of X with the reversed order 
    // bytes of Y, and then packs both of those into 4 bytes 
    // because we need to return an int (4 bytes). 
    byte[] xorbits = new byte[] { 
     (xbits[0]^ybits[7])^(xbits[4]^ybits[3]), 
     (xbits[1]^ybits[6])^(xbits[5]^ybits[2]), 
     (xbits[2]^ybits[5])^(xbits[6]^ybits[1]), 
     (xbits[3]^ybits[4])^(xbits[7]^ybits[0]), 
    }; 

    int value = 0; 
    for (int i = 0; i < 3; i++) { 
     value = (value << 8) + (by[i] & 0xff); 
    } 
    return value; 
} 

초기 최적화 나는를 캐시하는 것입니다 제안 후속 조회를 위해 오브젝트의 해시 코드를 작성하고, 프로파일 링이 문제가 있다고 제시하면 작성/삭제 된 어레이를보다 효율적으로 관리하십시오.

+0

답장을 보내 주셔서 감사합니다. 나는 당신의 대답에 대해 아직도 질문을 가지고 있습니다. 만약'단순히 y의 비트를 반전하고 xor x를 반대로하면'x == y'의 경우를 해결할 수 있을까요? –

+0

네, 왜냐하면'x == 10 '과'y == 10'의 단순한 경우에 이진 표현은 둘 다 (가상의 예제)'0x0000 0000 0000 0101'과 같은 것이기 때문에 y는 역순으로 바이트 순서가됩니다' 0x0101 0000 0000 0000'이고 xor는 편리하게 0x0101 0000 0000 0101이 될 것입니다. A^A = 0이라는 사실을 피할 수 있습니다. –

+0

아, 좋아, 바이트 역이며, 조금 뒤쪽이라고 생각했습니다. –

0

언어로 자바를 가지고,하지만 당신은 할 수 있어야 그게 맞습니까?) 비트 시프 팅, 매직 넘버 등으로 조금 다를 수 있습니다. 모든 종류의 비트 연산. 이 자바

인가? 나는 C#으로 내 경험에 대한 나의 대답을 근거로하고있다.

+0

예, 이것은 Java이지만 C#과 비슷하다고 생각합니다. 왜 이것이 효과가 있을지 더 설명해 주시겠습니까? 나는 해시하는 법에 대해 많이 모른다. 나는 x의 hashCode()와 y의 hashCode()를 얻는다. 왜 XOR은 유일한 해시를 제공 하는가? –

+1

@ JacksonTale : 고유 한 해시를 제공하지 않습니다. 물론, 위의 방법은 (a, b)가 (b, a)와 같은 해시로 해쉬된다는 단점이 있습니다. –

+0

포인트는 2 개의 128 개의 가능한 상태를 가지고 있기 때문에 유일한 해시를 보장 할 수는 없지만 가능한 해시 코드는 2^32 개뿐입니다. –

0

당신은 당신이 원하는 기능을 사용할 수 있습니다. 그것은 모두 좌표 값이 어떤 전형적인 값이고 해시 함수가 얼마나 좋은지에 달려 있습니다.

경우 예컨대 귀하의 모든 포인트는 1 백만에서 1 백만까지의 범위에 있으며, 다음과 같은 것을 사용할 수 있습니다 (이것은 C++ 코드이며, 사용하는 언어를 모르는 것입니다).

size_t hashCode = (size_t)x * (size_t)y; 

값을 추가하거나 값을 곱하거나 원하는대로 할 수 있습니다.

size_t hashCode = (size_t)(x+y); 

또는

size_t hashCode = (size_t)(x*y); 

또는

size_t hashCode = (size_t)(x*y) + (size_t)(x+y); 
+0

그는 태그가 나타내는대로 java를 사용하고 있습니다. size_t는 그러한 시스템에 존재하지 않습니다. 이는 실제로 솔루션에 대한 요구 사항입니다. –

관련 문제