2010-04-22 13 views
9

ja zdefiniował klasę:Python hash() nie obsługuje długiej liczby całkowitej?

 
class A: 
    ''' hash test class 
    >>> a = A(9, 1196833379, 1, 1773396906) 
    >>> hash(a) 
    -340004569 

    This is weird, 12544897317L expected. 
    ''' 
    def __init__(self, a, b, c, d): 
     self.a = a 
     self.b = b 
     self.c = c 
     self.d = d 

    def __hash__(self): 
     return self.a * self.b + self.c * self.d 

Dlaczego w doctest, hash function() daje ujemną liczbą całkowitą?

Odpowiedz

10

Wygląda na to, że jest ograniczony do 32-bitów. Po przeczytaniu this question wygląda na to, że Twój kod mógł wygenerować oczekiwany wynik na maszynie 64-bitowej (z tymi konkretnymi wartościami, ponieważ wynik mieści się w 64 bitach).

Wyniki wbudowanej funkcji hash zależą od platformy i są ograniczone do natywnego rozmiaru słowa. Jeśli potrzebujesz deterministycznego, mieszanego między platformami, rozważ użycie modułu hashlib.

4

Ponieważ celem funkcji skrótu jest pobranie zestawu wejść i rozłożenie ich na szereg klawiszy, nie ma powodu, aby te klucze były liczbami całkowitymi dodatnimi.

Fakt, że funkcja mieszania pythonów zwraca ujemne liczby całkowite, jest tylko szczegółem implementacji i jest koniecznie ograniczona do długich adresów int. Na przykład hash ("abc") jest ujemny w moim systemie.

7

Patrz object.__hash__

Należy zauważyć, że

Zmieniono w wersji 2.5 __hash__() może obecnie zwrócić długi przedmiot całkowitą; 32-bitowa liczba całkowita jest następnie wyprowadzana z mieszania tego obiektu.

W przypadku, spodziewać 12544897317L jest długi przedmiot całkowitą,

Pythona pochodzące z 32-bitową liczbę całkowitą -340004569 przez (12544897317 & 0xFFFFFFFF) - (1<<32)

Pythona pochodnej 32-bitową liczbę całkowitą od mieszania (12544897317L), co wynika -340004569

algorytmu jest coś takiego:

def s32(x): 
    x = x & ((1<<32)-1) 
    if x & (1<<31): 
     return x - (1<<32) 
    else: 
     return x 

def hash(x): 
    h = 0 
    while x: 
     h += s32(x) 
     x >>= 32 
    return h 
+2

Nitpick: (12544897317 & 0xFFFFFFFF) - (1 << 32) to nie -340004569; to jest -340004571. Python faktycznie dostaje się do 32-bitowej liczby przez * ponowne mieszanie *; tj. mieszanie obliczeniowe (12544897317). Jest to lepsze, ponieważ nie wyrzuca tylko bitów wyższego rzędu o oryginalnej wartości mieszania, ale zamiast tego miesza je w ostateczną wartość mieszania. –

+0

@ Mark Dickinson, uh-huh, dziękuję – inv

Powiązane problemy