Monday, 14 October 2013

C# Convert double to decimal

This is a workaround to Convert.ToDecimal(Double) limitation of 15 significant digits by using ‘R’ Round-trip Format Specifier.

Convert.ToDecimal Method (Double)
“The
Decimal value returned by this method contains a maximum of 15 significant digits. If the value parameter contains more than 15 significant digits, it is rounded using rounding to nearest. The following example illustrates how the Convert.ToDecimal(Double) method uses rounding to nearest to return a Decimal value with 15 significant digits.”

decimal.Parse(dbl.ToString("R"))
[Test]
public void ConvertDoubleToDecimal()
{
  Compare(1.00000000000006d,  1.00000000000006M);
  Compare(1.00000000000004d,  1.00000000000004M);
  Compare(1.000000000000066d, 1.000000000000066M);
  Compare(1.000000000000044d, 1.000000000000044M);
}
 
private void Compare(double dbl, decimal dec)
{
  Convert.ToDecimal("0.d0d.");
  var d1 = Convert.ToDecimal(dbl);
  var d2 = new Decimal(dbl);
  var d3 = decimal.Parse(dbl.ToString("R"));
  Console.WriteLine(@"
DOUBLE : {0:R}
CONVERT: {1} {2}
NEW  : {3} {4}
'R'  : {5} {6}", 
      dbl, 
      d1, d1.Equals(dec) ? "OK" : "FAILED",
      d2, d2.Equals(dec) ? "OK" : "FAILED", 
      d3, d3.Equals(dec) ? "OK" : "FAILED");
}
DOUBLE : 1.00000000000006
CONVERT: 1.00000000000006 OK
NEW    : 1.00000000000006 OK
'R'    : 1.00000000000006 OK
 
DOUBLE : 1.00000000000004
CONVERT: 1.00000000000004 OK
NEW    : 1.00000000000004 OK
'R'    : 1.00000000000004 OK
 
DOUBLE : 1.000000000000066
CONVERT: 1.00000000000007 FAILED
NEW    : 1.00000000000007 FAILED
'R'    : 1.000000000000066 OK
 
DOUBLE : 1.000000000000044
CONVERT: 1.00000000000004 FAILED
NEW    : 1.00000000000004 FAILED
'R'    : 1.000000000000044 OK

No comments:

Post a Comment