대략적인 동등성을 가진 float 해싱을 구현하는 방법 __init__(self, degrees):

다음과 같은 파이썬 클래스가 있다고 가정 해 봅시다 (문제는 Java와 equalsand와 동일합니다 hashCode)

class Temperature:
    def __init__(self, degrees):
        self.degrees = degrees

여기서 degreesfloat로서 켈빈 온도이다. 지금, 나는 평등 테스트 및 해싱을 구현하고자하는 Temperature방법한다는 점에서

  • 직접 평등 테스트 대신 엡실론 차이까지 플로트를 비교합니다.
  • a == b암시 하는 계약을 존중합니다 hash(a) == hash(b).
def __eq__(self, other):
    return abs(self.degrees - other.degrees) < EPSILON

def __hash__(self):
    return # What goes here?

파이썬 문서는 해싱 숫자 에 대해 조금 이야기 hash(2) == hash(2.0)하지만 이것이 같은 문제는 아닙니다.

내가 올바른 길을 가고 있습니까? 그렇다면이 상황에서 해싱을 구현하는 표준 방법은 무엇입니까?

업데이트 : 지금은 수레를 테스트 평등이 유형의 이행 성을 제거 이해 ==하고 equals. 그러나 이것이 어떻게 수레를 직접 비교해서는 안되는 “공통 지식”과 함께 진행됩니까? float를 비교하여 항등 연산자를 구현하면 정적 분석 도구가 불평합니다. 그들은 그렇게 할 권리가 있습니까?



답변

직접 등식 테스트 대신 부동 소수점을 엡실론 차이와 비교하는 방식으로 온도에 대한 등식 테스트 및 해싱을 구현합니다.

퍼지 평등 자바가에 배치하는 요구 사항을 위반하는 equals방법, 즉 이행 성 이있는 경우, 즉 x == y하고 y == z, 다음 x == z. 그러나 엡실론 0.1과 같은 퍼지 평등을 수행하면 0.1 == 0.2and 0.2 == 0.3이지만 0.1 == 0.3보유하지는 않습니다.

파이썬은 그러한 요구 사항을 문서화하지는 않지만, 전이가 아닌 평등을 갖는 것은 여전히 ​​나쁜 생각입니다. 이러한 유형에 대한 추론은 두통을 유발합니다.

그래서 나는 당신이 그렇게하지 않는 것이 좋습니다.

정확한 평등을 제공하고 명백한 방식으로 해시를 기반으로하고 퍼지 매칭을 수행하는 별도의 방법을 제공하거나 Kain이 제안한 동등성 클래스 접근 방식을 사용하십시오. 후자의 경우에는 생성자의 등가 클래스의 대표 멤버에 값을 고정 한 다음 나머지에 대해 간단한 정확한 평등과 해시를 사용하는 것이 좋습니다. 이런 식으로 유형을 추론하는 것이 훨씬 쉽습니다.

(그러나 그렇게하면 부동 소수점 대신 고정 소수점 표현을 사용할 수도 있습니다. 즉, 정수를 사용하여 천분의 1도 또는 필요한 정밀도를 계산할 수 있습니다.)


답변

행운을 빕니다

해시로 멍청하거나 엡실론을 희생시키지 않고는 그것을 달성 할 수 없습니다.

예:

각 포인트가 고유 한 해시 값으로 해시한다고 가정합니다.

부동 소수점 숫자는 순차적이므로 주어진 부동 소수점 값 이전에 최대 k 개의 숫자가 주어지며 주어진 부동 소수점 값 뒤에 주어진 k의 일부 엡실론 내에있는 최대 k 개의 숫자가 있습니다.

  1. 동일한 해시 값을 공유하지 않는 서로 다른 엡실론 내의 두 점마다.

    • 이 두 점이 같은 값으로 해시되도록 해싱 구성표를 조정하십시오.
  2. 이러한 모든 쌍에 대해 부동 소수점 숫자의 전체 시퀀스는 단일 값을 갖도록 축소됩니다.

이것이 사실이 아닌 몇 가지 경우가 있습니다.

  • 포지티브 / 네거티브 무한대
  • NaN
  • 주어진 엡실론의 기본 범위에 연결되지 않을 수있는 비정규 화 된 범위.
  • 아마도 몇 가지 다른 형식의 특정 인스턴스

그러나 부동 소수점 범위의> = 99 %는 주어진 부동 소수점 값 위 또는 아래에 하나 이상의 부동 소수점 값을 포함하는 엡실론 값에 대해 단일 값으로 해시됩니다.

결과

> = 99 % 전체 부동 소수점 범위 해시는 단일 값으로 해시 값의 의도를 심각하게 손상시킵니다 (그리고 상당히 분산 된 저 충돌 해시에 의존하는 모든 장치 / 컨테이너).

또는 엡실론은 정확히 일치하는 항목 만 허용됩니다.

세분화

물론 세분화 된 접근 방식으로 갈 수 있습니다.

이 방법에서는 정확한 버킷을 특정 해상도로 정의합니다. 즉 :

[0.001, 0.002)
[0.002, 0.003)
[0.003, 0.004)
...
[122.999, 123.000)
...

각 버킷에는 고유 한 해시가 있으며 버킷 내의 부동 소수점은 동일한 버킷의 다른 부동 소수점과 동일합니다.

불행히도 두 개의 수레가 엡실론 거리에 떨어져 있고 두 개의 분리 된 해시가 여전히 가능합니다.


답변

후드 아래에서 온도를 정수로 모델링 할 수 있습니다. 온도는 자연적으로 하한 (-273.15 ℃)입니다. 따라서 double (-273.15는 기본 정수의 경우 0과 같습니다). 두 번째로 필요한 요소는 매핑의 세분성입니다. 이미이 세분성을 암시 적으로 사용하고 있습니다. EPSILON입니다.

EPSILON으로 온도를 나누고 바닥을 가져 가면 해시와 동등한 것이 동기화됩니다. Python 3에서 정수는 제한이 없으며 EPSILON은 원하는 경우 더 작을 수 있습니다.

주의
EPSILON의 값을 변경하고 개체를 직렬화하면 호환되지 않습니다!

#Pseudo code
class Temperature:
    def __init__(self, degrees):
        #CHECK INVALID VALUES HERE
        #TRANSFORM TO KELVIN HERE
        self.degrees = Math.floor(kelvin/EPSILON)


답변

주어진 키와 “대략 같은”것을 찾을 수있는 부동 소수점 해시 테이블을 구현하려면 몇 가지 접근 방식 또는 그 조합을 사용해야합니다.

  1. 각 값을 해시 테이블에 저장하기 전에 “퍼지”범위보다 다소 큰 증분으로 반올림하고 값을 찾으려고 할 때 해시 테이블에서 찾은 값 위와 아래의 둥근 값을 확인하십시오.

  2. 원하는 값을 초과하는 키를 사용하여 해시 테이블 내에 각 항목을 저장하십시오.

두 가지 방법 중 하나를 사용하면 해시 테이블 항목이 항목을 식별하지 않고 목록으로 표시해야합니다. 각 키와 연관된 여러 항목이있을 수 있기 때문입니다. 위의 첫 번째 방법은 필요한 해시 테이블 크기를 최소화하지만 테이블에없는 항목을 검색 할 때마다 두 개의 해시 테이블 조회가 필요합니다. 두 번째 방법은 항목이 테이블에 없음을 신속하게 식별 할 수 있지만 일반적으로 필요한 경우보다 약 2 배 많은 항목을 테이블에 보유해야합니다. 2D 공간에서 객체를 찾으려면 X 방향과 Y 방향에 대해 하나의 접근 방식을 사용하는 것이 유용 할 수 있습니다. 따라서 각 항목을 한 번만 저장하는 대신 조회마다 4 개의 쿼리 작업이 필요하거나 한 번의 조회를 사용하여 항목을 찾을 수 있지만 각 항목을 4 번 저장해야합니다.


답변

가수의 마지막 8 비트를 삭제 한 다음 비교 또는 해싱을 통해 “거의 동일”을 정의 할 수 있습니다. 문제는 서로 매우 가까운 숫자 가 다를 있다는 것입니다.

여기에는 약간의 혼동이 있습니다. 두 개의 부동 소수점 숫자가 동일하게 비교되면 동일합니다. 이들이 같은지 확인하려면“==“를 사용하십시오. 때때로 당신은 평등을 확인하고 싶지 않지만, 그렇게 할 때“==“가가는 길입니다.


답변

이것은 답변이 아니지만 도움이 될 수있는 확장 된 설명입니다.

MPFR (GNU MP 기반) 을 사용하는 동안 비슷한 문제를 겪고 있습니다. @ Kain0_0에 의해 요약 된 “버킷”접근법은 수용 가능한 결과를 제공하는 것으로 보이지만 해당 답변에서 강조된 한계를 알고 있어야합니다.

Mathematica와 같은 “정확한” 컴퓨터 주의 대수 시스템을 사용하면 수행하려는 작업에 따라 부정확 한 수치 프로그램을 보완하거나 확인하는 데 도움이 될 수 있습니다. 이것은 당신이 예를 들어, 반올림에 대한 걱정없이 결과를 산출 할 수 있습니다 7*√2 - 5*√2얻을 것 2대신에 2.00000001또는 이와 유사한. 물론 이것은 가치가 있거나 없을 수도있는 추가 합병증을 유발할 것입니다.


답변