C # Почему одинаковые десятичные дроби могут давать неравные хеш-значения?

Мы столкнулись с магическим десятичным числом, которое нарушило нашу хеш-таблицу. Я свел его к следующему минимальному случаю:

decimal d0 = 295.50000000000000000000000000m;
decimal d1 = 295.5m;

Console.WriteLine("{0} == {1} : {2}", d0, d1, (d0 == d1));
Console.WriteLine("0x{0:X8} == 0x{1:X8} : {2}", d0.GetHashCode(), d1.GetHashCode()
                  , (d0.GetHashCode() == d1.GetHashCode()));

Получение следующего вывода:

295.50000000000000000000000000 == 295.5 : True
0xBF8D880F == 0x40727800 : False

Что на самом деле своеобразно: измените, добавьте или удалите любую из цифр в d0, и проблема исчезнет. Даже добавление или удаление одного из завершающих нулей! Знак, похоже, не имеет значения.

Наше решение состоит в том, чтобы разделить значение на избавьтесь от завершающих нулей, например:

decimal d0 = 295.50000000000000000000000000m / 1.000000000000000000000000000000000m;

Но у меня вопрос, почему C # делает это неправильно?

edit: Просто заметил, что это было исправлено в .NET Core 3.0 (возможно, раньше, я не делал этого) не проверяю): https://dotnetfiddle.net/4jqYos

42
задан Jannes 25 November 2019 в 16:40
поделиться