Математическое объяснение, почему преобразование десятичного числа в двойное не работает, а Decimal.GetHashCode разделяет равные экземпляры
Я не уверен, является ли этот нестандартный способ постановки вопроса переполнения стека хорошим или плохим, но здесь идет речь:
Какое лучшее (математическое или иное техническое) объяснение, почему код:
static void Main()
{
decimal[] arr =
{
42m,
42.0m,
42.00m,
42.000m,
42.0000m,
42.00000m,
42.000000m,
42.0000000m,
42.00000000m,
42.000000000m,
42.0000000000m,
42.00000000000m,
42.000000000000m,
42.0000000000000m,
42.00000000000000m,
42.000000000000000m,
42.0000000000000000m,
42.00000000000000000m,
42.000000000000000000m,
42.0000000000000000000m,
42.00000000000000000000m,
42.000000000000000000000m,
42.0000000000000000000000m,
42.00000000000000000000000m,
42.000000000000000000000000m,
42.0000000000000000000000000m,
42.00000000000000000000000000m,
42.000000000000000000000000000m,
};
foreach (var m in arr)
{
Console.WriteLine(string.Format(CultureInfo.InvariantCulture,
"{0,-32}{1,-20:R}{2:X8}", m, (double)m, m.GetHashCode()
));
}
Console.WriteLine("Funny consequences:");
var h1 = new HashSet<decimal>(arr);
Console.WriteLine(h1.Count);
var h2 = new HashSet<double>(arr.Select(m => (double)m));
Console.WriteLine(h2.Count);
}
дает следующий «забавный» (явно неправильный) вывод:
42 42 40450000 42.0 42 40450000 42.00 42 40450000 42.000 42 40450000 42.0000 42 40450000 42.00000 42 40450000 42.000000 42 40450000 42.0000000 42 40450000 42.00000000 42 40450000 42.000000000 42 40450000 42.0000000000 42 40450000 42.00000000000 42 40450000 42.000000000000 42 40450000 42.0000000000000 42 40450000 42.00000000000000 42 40450000 42.000000000000000 42 40450000 42.0000000000000000 42 40450000 42.00000000000000000 42 40450000 42.000000000000000000 42 40450000 42.0000000000000000000 42 40450000 42.00000000000000000000 42 40450000 42.000000000000000000000 41.999999999999993 BFBB000F 42.0000000000000000000000 42 40450000 42.00000000000000000000000 42.000000000000007 40450000 42.000000000000000000000000 42 40450000 42.0000000000000000000000000 42 40450000 42.00000000000000000000000000 42 40450000 42.000000000000000000000000000 42 40450000 Funny consequences: 2 3
Попробовал это под .NET 4.5.2.