c# .net hash floating-point nan

c# - ¿Por qué Microsoft querría NO arreglar las implementaciones incorrectas de Equals y GetHashCode con NaN?



gethashcode c# (0)

En .NET Framework, la implementación ( override ) de Equals(object) y GetHashCode() para los tipos de coma flotante ( System.Double y System.Single ) es incorrecta . Para citar de la especificación MSDN GetHashCode(object) :

Una función hash debe tener las siguientes propiedades:

• Si dos objetos se comparan como iguales, el método GetHashCode para cada objeto debe devolver el mismo valor. Sin embargo, si dos objetos no se pueden comparar como iguales, los métodos GetHashCode para los dos objetos no tienen que devolver valores diferentes.

Si toma dos valores NaN con diferentes representaciones binarias, los dos objetos se comparan iguales bajo el método Equals , pero los códigos hash son (casi siempre) distintos.

Ahora, este error ha sido reportado en Microsoft Connect. ¿Pero por qué no arreglarán esto?

La solución es sencilla: permita que diferentes NaN no se comparen como iguales, o elija un código hash fijo para devolver cualquier NaN .

La solución no romperá nada: tal como están las cosas hoy en día, nada funciona cuando se usan diferentes NaN .

¿Puedes pensar en alguna razón para no arreglar esto?

Aquí hay un ejemplo simple que ilustra el comportamiento actual:

using System; using System.Collections.Generic; using System.Linq; static class Program { const int setSize = 1000000; // change to higher value if you want to waste even more memory const double oneNaNToRuleThemAll = double.NaN; static readonly Random randomNumberGenerator = new Random(); static void Main() { var set = new HashSet<double>(); // uses default EqualityComparer<double> while (set.Count < setSize) set.Add(GetSomeNaN()); Console.WriteLine("We now have a set with {0:N0} members", set.Count); bool areAllEqualToTheSame = set.All(oneNaNToRuleThemAll.Equals); if (areAllEqualToTheSame) Console.WriteLine("By transitivity, all members of the set are (pairwise) equal."); } static double GetSomeNaN() // can also give PositiveInfinity, NegativeInfinity (unlikely) { byte[] b = new byte[8]; randomNumberGenerator.NextBytes(b); b[7] |= 0x7F; b[6] |= 0xF0; return BitConverter.ToDouble(b, 0); } }

Resultado de ejecutar el código: Un millón de duplicados en un HashSet<> .

TENGA EN CUENTA: Esto no tiene nada que ver con los operadores == y != C #. Utilice Equals si desea verificar esto usted mismo.