简体   繁体   中英

String.Format with infinite precision and at least 2 decimal digit

I am developing an application for some guys very picky about numerical accuracy (they are dealing among others with accounting and very accurate telecom variables). For this reason I am using the decimal type everywhere, because the float and double types are not suitable (do not hesitate to redirect me to an existing better datatype).

My problem comes when I need to format those numbers. The requirement is to display as many decimal digit as needed but at least 2 and also to use a group separator for thousands.

For example:

Value       Formatted
1                1.00
1000         1,000.00
1.5              1.50
1000.355    1,000.355
0.000035     0.000035

So I went the MSDN looking for numeric string formats. I found this useful resource Standard Numeric Formats but none of my tries works as expected (N, N2, F, F2, G, G2, etc, I tried various combinations even when I didn't believe in them ^^ - I even try some F2# for fun).

My conclusion is there is not a built-in format to do what I want. Right?

So I checked out the next chapter Custom Numeric Formats . But I couldn't find a combination that suit my needs. So I went to SO and find a lots of question about that ( 1 , 2 , and so on).

These questions let me fear that the only solution is this one: #,##0.00####### with as many trailing # as I need precision.

Am I right?

I guess that with 12 #, my guys won't find any accuracy issue, but I might have missed the magical format I need?

This is probably what you're looking for:

static string FormatNumber(string input)
{
    var dec = decimal.Parse(input);
    var bits = decimal.GetBits(dec);
    var prec = bits[3] >> 16 & 255;
    if (prec < 2)
        prec = 2;
    return dec.ToString("N" + prec);
}

When you call it, do a ToString() on decimals, and convert the result back to decimal if needed.

I tried your example numbers, and the result:

在此输入图像描述

Based on this SO answer .

I created a little function: it formats the number based on how many decimal places it has:

    public static void Main()
    {
        decimal theValue;
        theValue = 0.000035M;
        Console.WriteLine(theFormat(theValue));
        theValue = 1.5M;
        Console.WriteLine(theFormat(theValue));
        theValue = 1;
        Console.WriteLine(theFormat(theValue));                 
    }
    public static decimal theFormat(decimal theValue){
        int count = BitConverter.GetBytes(decimal.GetBits(theValue)[3])[2];
        return count > 1?theValue:Convert.ToDecimal(string.Format("{0:F2}", theValue));
    }

This, produces the following output:

0.000035
1.50
1.00

If you want a total control over formatting you can implement your own IFormatProvider for decimals. Inside of it you can use StringBuilder and do anything you need with no restrictions of string.Format().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM