Przeczytam przez Chapter 3 z Joshua Blocha Skuteczna Java. W punkt 8: zawsze zastępują hashCode kiedy przesłonić równa, autor wykorzystuje następujące łącząc krok w swej funkcji haszowania:Mnożenie liczby całkowitej, przepełnienie i utrata informacji
result = 37 * result + c;
Potem wyjaśnia, dlaczego 37 została wybrana (podkreślenie dodane):
Mnożnik 37 został wybrany, ponieważ jest to nieparzysta liczba pierwsza. Jeśli był równy i , to mnożenie uległo przepełnieniu, informacje zostałyby utracone, ponieważ pomnożenie przez dwa jest równoznaczne z przesunięciem. Zalety korzystania z numeru pierwszego są mniej wyraźne, ale jest to typowe użycie liczb pierwszych w tym celu.
Moje pytanie brzmi, dlaczego to ma znaczenie, że czynnik łączący (37) jest dziwne? Czy przepełnienie mnożenia nie spowodowałoby utraty informacji, niezależnie od tego, czy czynnik był nieparzysty czy nawet niepoprawny?
Ah, więc nie jest to po prostu odrobina utraty informacji, którą można uzyskać z przepełnienia, o które się martwimy, jest to * pełne * utrata informacji, którą można uzyskać od wyzerowania wyniku? –
@BilltheLizard: w rzeczywistości to dane z wielu właściwości emulujących się nawzajem. Zakładając trzy właściwości a, b i c, używając powyższego algorytmu 'result = 2 * (2 * a + b) + c', widać, że będzie powielanie w wielu prawdopodobnie wspólnych zestawach' a, b, c'. Jeśli używasz nieparzystej liczby pierwszej jako stałej, możliwość uzyskania zestawu o tych samych wartościach mieszania staje się znacznie mniejsza. –
Problem pojawia się, zanim całkowicie wyzerujesz wynik. Rozważ zwielokrotnienie 8-bitowego skrótu przez mnożnik dwóch tylko raz - zaczyna się od 256 możliwych wartości, a kończy 128 możliwymi wartościami. –