避免 decimal.TryParse 将“1.1.1”或“1,1,1”识别为十进制

Avoid decimal.TryParse to recognize "1.1.1" or "1,1,1" as decimal

我在字符串识别方面遇到了问题:我试图只识别格式正确的数字,但找不到方法。

我正在编写文化不变的方式,所以我需要识别“,”和“。”作为小数点和千位分隔符,反之亦然。

所有这些对我来说都是正确的格式:

12,1
12.1
1.000,12
1,000.12

但是这样的事情是错误的

1.2.3
1,2,3

我试过了:

NumberStyles style;
decimal n;  
object valore;                                  
style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowThousands;

Console.WriteLine(decimal.TryParse(valore.ToString(), style , CultureInfo.InvariantCulture, out n));

this is the fiddle to test it

但是“1,1,1”被读取为有效数字,而“1.1.1”不是。

如果我使用我的特定区域性 ("it-IT"),“1,1,1”会被识别,而“1.1.1”不会。

如何丢弃所有无效字符串?

我用个人解析器结束了这个,我希望找到更好的解决方案,但阅读评论似乎是不可能的

public static bool tryValoreNumerico(object valore, out decimal valoreRestituito)
    {
        decimal n;          
        string testoNormalizzato;

        valoreRestituito = 0;

        // normalizzazione
        if (valore.ToString().Contains(",") && valore.ToString().Contains("."))
        {
            if (valore.ToString().IndexOf(".") < valore.ToString().IndexOf(","))
            {
                testoNormalizzato = valore.ToString().Replace(".", "");
            }
            else
            {
                testoNormalizzato = valore.ToString().Replace(",", "");
            }
        }
        else
        {
            if ((valore.ToString().Length - valore.ToString().Replace(",", "").Length) > 1)
            {
                string[] pezzi = valore.ToString().Split(',');
                for (int i = 1; i < pezzi.Length; i++ )
                {
                    if (pezzi[i].Length != 3)
                        return false;
                }

                testoNormalizzato = valore.ToString().Replace(",", "");
            }
            else if ((valore.ToString().Length - valore.ToString().Replace(".", "").Length) > 1)
            {
                string[] pezzi = valore.ToString().Split('.');
                for (int i = 1; i < pezzi.Length; i++)
                {
                    if (pezzi[i].Length != 3)
                        return false;
                }

                testoNormalizzato = valore.ToString().Replace(".", "");
            }

            else
                testoNormalizzato = valore.ToString();

        }
        testoNormalizzato = testoNormalizzato.Replace(",", ".");

        if (decimal.TryParse(testoNormalizzato, out n) && testoNormalizzato == Convert.ToDecimal(testoNormalizzato, new CultureInfo("en-US")).ToString().Replace(",", "."))
        {
            valoreRestituito = Convert.ToDecimal(testoNormalizzato, new CultureInfo("en-US"));
        }
        return decimal.TryParse(testoNormalizzato, out n) && testoNormalizzato == Convert.ToDecimal(testoNormalizzato, new CultureInfo("en-US")).ToString().Replace(",", ".");

    }

简而言之,首先我将数字标准化为 EN 格式,然后尝试将其转换

最后的测试是查看没有文本 "similar" 到数字,因为像“001”、“100 01”这样的字符串不是数字。

比例是:每个字符串必须保持不变:“001”转换为数字变成“1”,与原始值不同,因此必须避免这种转换

this is the fiddle

我建议您使用 Regex 进行验证,并使用如下自定义解析方法:

public static decimal DecimalParse(string number)
{
    if (new Regex(@"^\d+$").IsMatch(number))
    {
        return decimal.Parse(number, CultureInfo.InvariantCulture);
    }
    if (new Regex(@"^(\d{0,3}(,\d{3})*(\.\d+)?)$").IsMatch(number))
    {
        return decimal.Parse(number, CultureInfo.InvariantCulture);
    }
    return new Regex(@"^(\d{0,3}(\.\d{3})*(,\d+)?)$").IsMatch(number)
        ? decimal.Parse(number.Replace(".", "").Replace(",", "."), CultureInfo.InvariantCulture)
        : 0;
}

结果将是:

string num;
num = "1,000";      Console.WriteLine("{0}", DecimalParse(num));     //1000
num = ",01";        Console.WriteLine("{0}", DecimalParse(num));     //0.01
num = ".02";        Console.WriteLine("{0}", DecimalParse(num));     //0.02
num = "12,1";       Console.WriteLine("{0}", DecimalParse(num));     //12.1
num = "12.1";       Console.WriteLine("{0}", DecimalParse(num));     //12.1
num = "1.000,12";   Console.WriteLine("{0}", DecimalParse(num));     //1000.12
num = "1.000.000,12"; Console.WriteLine("{0}", DecimalParse(num));   //1000000.12
num = "1,000.12";   Console.WriteLine("{0}", DecimalParse(num));     //1000.12
num = "1,000,000.12"; Console.WriteLine("{0}", DecimalParse(num));   //1000000.12
num = "1000";       Console.WriteLine("{0}", DecimalParse(num));     //0
num = "110.";       Console.WriteLine("{0}", DecimalParse(num));     //0
num = "110,";       Console.WriteLine("{0}", DecimalParse(num));     //0
num = "1.2.3";      Console.WriteLine("{0}", DecimalParse(num));     //0
num = "1,2,3";      Console.WriteLine("{0}", DecimalParse(num));     //0