2
\$\begingroup\$

Requirements:

  1. Must convert a double to a string, without losing any digits.
  2. Cannot use scientific notation.

In C#, no format string exists that you can you pass into Double.ToString(format) to accomplish this, because ToString will use only 15 digits, even though a double can have 17. Although R and G17 can use 17 digits, it may or may not use scientific notation.

Please correct me if I am wrong.

Therefore, I wrote a function to do this. I'm posting it here as an optimization question. If you see flaws, feel free to point them out. I'm confident the code works, but there's plenty of room for improvement.

[Fact]
public void NumberFormats()
{
    double d1 = 123456789012171.23;
    double d2 = 0.0000000000000001;
    double d3 = 10000000000000000;

    string s1 = DoubleToString(d1);
    string s2 = DoubleToString(d2);
    string s3 = DoubleToString(d3);

    Assert.Equal("123456789012171.23", s1);
    Assert.Equal("0.0000000000000001", s2);
    Assert.Equal("10000000000000000", s3);
}

private string DoubleToString(double d)
{
    string R = d.ToString("R", CultureInfo.InvariantCulture).Replace(",", "");
    int i = R.IndexOf('E');

    if (i < 0)
        return R;

    string G17 = d.ToString("G17", CultureInfo.InvariantCulture);

    if (!G17.Contains('E'))
        return G17.Replace(",", "");

    // manual parsing
    string beforeTheE = R.Substring(0, i);
    int E = Convert.ToInt32(R.Substring(i + 1));

    i = beforeTheE.IndexOf('.');

    if (i < 0)
        i = beforeTheE.Length;
    else
        beforeTheE = beforeTheE.Replace(".", "");

    i += E;

    while (i < 1)
    {
        beforeTheE = "0" + beforeTheE;
        i++;
    }

    while (i > beforeTheE.Length)
    {
        beforeTheE += "0";
    }

    if (i == beforeTheE.Length)
        return beforeTheE;

    return String.Format("{0}.{1}", beforeTheE.Substring(0, i), beforeTheE.Substring(i));
}
\$\endgroup\$

migrated from stackoverflow.com Dec 9 '16 at 10:06

This question came from our site for professional and enthusiast programmers.

  • 1
    \$\begingroup\$ take a look at this posting and it gives you some good examples on how to convert a double to a string using the string.Format() function stackoverflow.com/questions/4670218/… \$\endgroup\$ – MethodMan Dec 8 '16 at 14:56
  • 3
    \$\begingroup\$ a double can have 17 - No. double doesn't have 17 significant digits. \$\endgroup\$ – TaW Dec 8 '16 at 15:01
  • \$\begingroup\$ Not all doubles have 17 digits, but some do. I have one in my example. TaW take a look at the G17 format string and why it is important, and also take a look at how the R format string is handled. Then you'll understand the problem. \$\endgroup\$ – Cobaltikus Dec 10 '16 at 17:12
  • \$\begingroup\$ csharpindepth.com/Articles/General/FloatingPoint.aspx may be of interest. In this article there is a link to a DoubleConverter class which has a ToExactString method that may be of interest. It works very differently than yours ignoring any built in stuff and looking directly at the binary representation of the number. Obviously doesn't help with a review on your code but thought it might be of interest. \$\endgroup\$ – Chris Jan 8 '17 at 17:33
1
\$\begingroup\$

I know, it's a challenge convert your big doubles to string, but if you can use decimal instead of double, the conversion could be smooth.

static void Main(string[] args)
{
    decimal d1 = 123456789012171.23m;
    decimal d2 = 0.0000000000000001m;
    decimal d3 = 10000000000000000m;

    Console.WriteLine(d1);
    Console.WriteLine(d2);
    Console.WriteLine(d3);
}
\$\endgroup\$
  • \$\begingroup\$ Unless your double is NaN, PositiveInfinity, or NegativeInfinity which aren't representable by Decimal. \$\endgroup\$ – Rick Davin Mar 9 '17 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.