Это неудачно, я думаю. Около 139 000 Decimal
имеет гораздо лучшую точность, чем Double
. Но, тем не менее, из-за этой проблемы у нас разные Double
проецируются на те же самые Decimal
. Например
double doub1 = 138630.7838038626;
double doub2 = 138630.7838038628;
Console.WriteLine(doub1 < doub2); // true, values differ as doubles
Console.WriteLine((decimal)doub1 < (decimal)doub2); // false, values projected onto same decimal
На самом деле существует шесть различных представляемых Double
значений между doub1
и doub2
выше, поэтому они не совпадают.
Вот несколько глупая работа-aronud:
static decimal PreciseConvert(double doub)
{
// Handle infinities and NaN-s first (throw exception)
// Otherwise:
return Decimal.Parse(doub.ToString("R"), NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
}
Строка формата "R"
обеспечивает включение достаточного количества дополнительных цифр, чтобы сделать инъекцию сопоставления (в области, где Decimal
имеет превосходную точность).
Обратите внимание, что в некотором диапазоне long
(Int64
) имеет точность, превосходящую точность Double
. Таким образом, я проверил, выполняются ли здесь преобразования аналогичным образом (сначала округляя до 15 значащих десятичных разрядов). Они не! Итак:
double doub3 = 1.386307838038626e18;
double doub4 = 1.386307838038628e18;
Console.WriteLine(doub3 < doub4); // true, values differ as doubles
Console.WriteLine((long)doub3 < (long)doub4); // true, full precision of double used when converting to long
Кажется непоследовательным использовать другое «правило», когда целью является decimal
.
Обратите внимание, что из-за этого (decimal)(long)doub3
дает более точный результат, чем просто (decimal)doub3
.