¿Por qué se usa '397' para la anulación de ReSharper GetHashCode?

150

Como muchos de ustedes, uso ReSharper para acelerar el proceso de desarrollo. Cuando lo usa para anular los miembros de igualdad de una clase, el código-gen que produce para GetHashCode () se ve así:

    public override int GetHashCode()
    {
        unchecked
        {
            int result = (Key != null ? Key.GetHashCode() : 0);
            result = (result * 397) ^ (EditableProperty != null ? EditableProperty.GetHashCode() : 0);
            result = (result * 397) ^ ObjectId;
            return result;
        }
    }

Por supuesto que tengo algunos de mis propios miembros allí, pero lo que quiero saber es por qué 397?

  • EDITAR: Entonces mi pregunta estaría mejor redactada, ¿hay algo 'especial' en que el número primo 397 fuera de él sea un número primo?
programador
fuente

Respuestas:

166

Probablemente porque 397 es un primo de tamaño suficiente para causar que la variable de resultado se desborde y mezcle un poco los bits del hash, proporcionando una mejor distribución de los códigos hash. No hay nada particularmente especial en el 397 que lo distinga de otros números primos de la misma magnitud.

Nick Johnson
fuente
73
Y 397 es feliz. ¿No todos queremos ser felices?
Russell B
2
Bien, pero ¿por qué tiene que ser primo y por qué tiene que ser de esa magnitud exacta? Si tiene que ser primo, ¿por qué no 2 o 2147483647? Supongo que para obtener una buena mutación (y la única razón de esta multiplicación es la mutación) no necesitamos números para ser primos. Necesitamos multiplicador para tener relativamente el mismo número o ceros y unos, preferiblemente sin patrones explícitos. 397 = 110001101b cumple. Todavía no estoy seguro de la magnitud.
Andriy K
55
Como dijo Nick, no tiene nada de especial. No NECESITA ser de ese tamaño, es solo un número lo suficientemente grande como para que cuando esté calculando un hash el resultado se desborde (ya que GetHashCode () devuelve un Int32). Seleccionar un primo solo es útil para la distribución, no tengo un título en matemáticas, así que no voy a tratar de explicarlo, pero la multiplicación por un primo tendrá un resultado que está mejor distribuido que la multiplicación por cualquier otro número arbitrario.
Ben Randall,
16

El hash que usa resharper parece una variante del hash FNV . FNV se implementa frecuentemente con diferentes números primos. Hay un debate sobre la elección apropiada de los números primos para FNV aquí .

Kybernetikos
fuente