Причиной наблюдаемого поведения является то, что реализация Microsoft C # преобразует float
в decimal
, используя только семь десятичных цифр.
В реализации Microsoft C # используется .NET. Когда .NET преобразует число с плавающей запятой одинарной точности в десятичное, выдает не более семи значащих цифр , округляя любой остаток с использованием округления до ближайшего.
Исходный текст 0.1F
становится значением одинарной точности 0.100000001490116119384765625. Когда он преобразуется в десятичную с семью значащими цифрами, результат равен точно 0,1. Таким образом, в Microsoft C # (decimal) 0.1F
выдает 0.1, поэтому (decimal) 0.1F == 0.1M
имеет значение true.
Мы можем сравнить это с реализацией не Microsoft, Mono C #. Онлайн-компилятор для этого доступен здесь . В нем Console.WriteLine((decimal)0.1F);
печатает «0.100000001490116», а (decimal)0.1F == 0.1M
оценивается как ложное. Mono C # при преобразовании float
в decimal
.
выдает более семи цифр.
Документация Microsoft C # для явных преобразований гласит: «При преобразовании float
или double
в decimal
исходное значение преобразуется в десятичное представление и округляется до ближайшего числа после 28-го десятичного знака поместите, если требуется. »Я бы интерпретировал это как означающее, что истинное значение float
, 0.100000001490116119384765625, точно преобразуется в decimal
(так как для него требуется менее 28 цифр), но, очевидно, это не так.
Мы можем далее подтвердить это и проиллюстрировать, что происходит, преобразовав float
в double
, а затем в decimal
. Microsoft C # преобразует double
в decimal
, используя 15 значащих цифр. Если мы конвертируем 0.1F
в double
, значение не меняется, поскольку double
может точно представлять каждое float
значение , Так что (double) 0.1F
имеет точно такое же значение, как и 0.1F
, 0.100000001490116119384765625. Однако теперь, когда он преобразуется в decimal
, получается 15 цифр. В реализации Microsoft C # Console.WriteLine((decimal)(double) 0.1F);
печатает «0.100000001490116», а (decimal)(double) 0.1F == 0.1M
оценивается как ложное.