C# Convert string to double/decimal and back to st

2019-06-21 08:35发布

问题:

I am trying to get user input, parse it and then display with String.Format(), formatting thousands with comas.

So, if user provides
1000  I will display 1,000
1000.00 => 1,000.00
1000.0  => 1,000.0
1,000.5 => 1,000.5

Basically I want to keep all decimals(including trailing zeroes) that were provided and just add formatting for thousands. I tried:

String.Format("{0:#,0.######}" , Decimal.Parse(input));
String.Format("{0:#,0.######}" , Double.Parse(input);

回答1:

double.Parse(input) is a no go, as double does not keep track of the number of decimals.

decimal.Parse(input).ToString() will show that decimal does keep track of that. Unfortunately, decimal.Parse(input).ToString() uses this precision and doesn't use a thousands separator, and decimal.Parse(input).ToString("N") ignores the precision but does use a thousands separator.

Manually extracting the precision from the decimal works though, and that allows you to build the correct format string:

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

This is based on the layout of decimal as described on MSDN:

Bits 16 to 23 must contain an exponent between 0 and 28, which indicates the power of 10 to divide the integer number.

See it working on .NET Fiddle. (courtesy of @Alisson)



回答2:

You can use regex for this:

var input = "1000.50000";
var regex = new Regex("^(?<int>-?[\\d,]+)\\.(?<fract>\\d+)$");
var match = regex.Match(input);
var integralPart = match.Groups["int"].Value.Replace(",", "");
var fractionalPart = match.Groups["fract"].Value;
var result = $"{decimal.Parse(integralPart):n0}.{fractionalPart}";


回答3:

        public string DoFormat(string num)
    {
        int pt = num.IndexOf(".");
        if (pt > 0)
        {
            return string.Format("{0:#,##0}", num.Substring(0, pt)) + num.Substring(pt, num.Length - pt);
        }
        else
        {
            return string.Format("{0:#,##0}", num);
        }
    }

This splits the string at the decimal point and returns whatever is after the decimal point as was typed in BUT formats the integer part of the number with commas.



回答4:

If you don't mind 1000 converted to 1,000.00 then following is the best as it considers user's locale too.

string output = String.Format("{0:n}", input);

If you want 1000 converted to just 1,000, then you can use the following:

string output2 = String.Format("{0:#,##0.##}", input);