I have a double "138630.78380386264"
and I want to convert it to a decimal, however when I do so I do it either by casting or by using Convert.ToDecimal()
and I lose precision.
What's going on? Both decimal and double can hold this number:
double doub = double.Parse("138630.78380386264");
decimal dec = decimal.Parse("138630.78380386264");
string decs = dec.ToString("F17");
string doubse =DoubleConverter.ToExactString(doub);
string doubs = doub.ToString("F17");
decimal decC = (decimal) doub;
string doudeccs = decC.ToString("F17");
decimal decConv = Convert.ToDecimal(doub);
string doudecs = decConv.ToString("F17");
Also: how can I get the ToString()
on double to print out the same result as the debugger shows? e.g. 138630.78380386264
?
138630.78380386264
is not exactly representable to double precision. The closest double precision number (as found here) is138630.783803862635977566242218017578125
, which agrees with your findings.You ask why the conversion to decimal does not contain more precision. The documentation for
Convert.ToDecimal()
has the answer:The double value, rounded to nearest at 15 significant figures is
138630.783803863
, exactly as you show above.It is a unfortunate, I think. Near 139,000, a
Decimal
has far better precision than aDouble
. But still, because of this issue, we have differentDouble
s being projected onto the sameDecimal
. For exampleIn fact there are six different representable
Double
values betweendoub1
anddoub2
above, so they are not the same.Here is a somewhat silly work-aronud:
The
"R"
format string ensures that enough extra figures are included to make the mapping injective (in the domain whereDecimal
has superior precision).Note that in some range, a
long
(Int64
) has a precision that is superior to that ofDouble
. So I checked if conversions here are made in the same way (first rounding to 15 significant decimal places). They are not! So:It seems inconsistent to use a different "rule" when the target is
decimal
.Note that because of this,
(decimal)(long)doub3
produces a more accurate result than just(decimal)doub3
.