Format a double value to fit into a maximum string size

牧云@^-^@ 提交于 2019-12-25 02:42:58

问题


I need to format a double value so that it fits within a field of 13 characters. Is there a way to do this with String.Format or am I stuck with character-by-character work?

Edits: (hopefully they will stay this time)

With cases greater than a trillion I am to report an error. It's basically a calculator interface.

My own answer:

private void DisplayValue(double a_value)
{
    String displayText = String.Format("{0:0." + "".PadRight(_maxLength, '#') + "}", a_value);

    if (displayText.Length > _maxLength)
    {
        var decimalIndex = displayText.IndexOf('.');
        if (decimalIndex >= _maxLength || decimalIndex < 0)
        {
            Error();
            return;
        }

        var match = Regex.Match(displayText, @"^-?(?<digits>\d*)\.\d*$");
        if (!match.Success)
        {
            Error();
            return;
        }

        var extra = 1;
        if (a_value < 0)
            extra = 2;

        var digitsLength = match.Groups["digits"].Value.Length;
        var places = (_maxLength - extra) - digitsLength;

        a_value = Math.Round(a_value, places);

        displayText = String.Format("{0:0." + "".PadRight(_maxLength, '#') + "}", a_value);

        if (displayText.Length > _maxLength)
        {
            Error();
            return;
        }
    }

    DisplayText = displayText;
}

回答1:


If this is calculator, then you can not use character-by-character method you mention in your question. You must round number to needed decimal places first and only then display it otherwise you could get wrong result. For example, number 1.99999 trimmed to length of 4 would be 1.99, but result 2 would be more correct.

Following code will do what you need:

int maxLength = 3;
double number = 1.96;
string output = null;
int decimalPlaces = maxLength - 2; //because every decimal contains at least "0."
bool isError = true;

while (isError && decimalPlaces >= 0)
{
    output = Math.Round(number, decimalPlaces).ToString();
    isError = output.Length > maxLength;
    decimalPlaces--;
}

if (isError)
{
    //handle error
}
else
{
    //we got result
    Debug.Write(output);
}



回答2:


You have a lot formatting options using String.Format, just specify format after placeholder like this {0:format}.

Complete example looks like this:

Console.WriteLine("Your account balance is {0:N2}.", value);

Output would be:

Your account balance is 15.34.

All of the options for numeric types are listed here:

http://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx




回答3:


This seems to work for me (but is hand-rolled):

    static string FormatDouble(double d)
    {
        int maxLen = 13;
        double threshold = Math.Pow(10, maxLen);

        if (d >= threshold || d <= 0 - (threshold/10))
            return "OVERFLOW";
        string strDisplay = "" + d;
        if (strDisplay.Length > maxLen )
            strDisplay = strDisplay.Substring(0, maxLen);
        if (strDisplay.EndsWith("."))
            strDisplay = strDisplay.Replace(".", "");
        return strDisplay;
    }

Let me know if it gives you trouble with scientific notation creeping in. I believe the format "{0:R}" should help you avoid that explicitly.

Also, I wasn't sure if you were including +/- sign in digit count or if that was in a separate UI slot.

The theory on rounding here is that, yes, "" + d might round some things, but in general it's going to be many more digits out than are ever displayed so it shouldn't matter. So this method should always truncate.

Here's a solution that does rounding. (I couldn't think of a non-mathematical way to do it):

    static string FormatDouble(double d)
    {
        int maxLen = 13;
        int places = (int)Math.Max(Math.Log10(Math.Abs(d)), 0);
        places += (d == Math.Abs(d) ? 1 : 2);
        if (places > maxLen || places < 1 - maxLen)
            return "OVERFLOW";
        if (Math.Floor(d) == d) ++places;  // no decimal means one extra spot 
        d = Math.Round(d, Math.Max(maxLen - places - 1, 0));
        return string.Format("{0:R}", d);
    }

Note: I still think your users might appreciate seeing something closer to what is being stored in the underlying memory than what is often typical of calculators. (I especially hate the ones that can turn 0.99 into 1.01) Either way, you've got at least 3 solutions now so it's up to you.



来源:https://stackoverflow.com/questions/20403497/format-a-double-value-to-fit-into-a-maximum-string-size

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!