FNV-0 in Python

Piccolo code snippet per estimatori del pitone.

  1. def fnv_hash(data):
  2.    """
  3.    Returns a 32bit FNV-0 hash of the given string.
  4.  
  5.    >>> fnv_hash('3dcb910fb26bafb97e4a9660493afd9704536743')
  6.    -1588890617L
  7.    >>> fnv_hash('deb114355f8b912c4f7c7f0aceac7adceaa5db10')
  8.    317390073L
  9.    """
  10.    h = long(0)
  11.    for i in xrange(len(data)):
  12.       h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)
  13.       h ^= ord(data[i])
  14.    # Everything after the 32th bit is meaningless
  15.    h &= 0xffffffffL
  16.    # Perform sign extension
  17.    if h & 0x80000000L:
  18.        h = -(~(h – 1) & 0xffffffffL)
  19.    return h
  20.  

I compagni di merende che masticano C avranno sicuramente storto il naso vedendo sia l'AND che l'estensione di segno fatta in quel modo becero, quindi precisiamo:

  • Python promuove automaticamente gli interi alla storage class superiore (ANCHE oltre i 64 bit) per evitare l'overflow, quindi solo i 32 bit inferiori contengono valori sensati;
  • per quanto appena esposto, l'estensione di segno non può essere effettuata con un banale OR (che promuoverebbe l'intero per conservare il segno!) ma è necessario fare ricorso alla definizione scolastica di complemento a 2.

Leave a Reply