解析任意格式字符串中的十进制数

3

下面是next方法的任何实现:

public static decimal StringToDecimal(string sValue)
{
    if (string.IsNullOrEmpty(sValue))
    {
        return 0;
    }
    ...
}

我的应用程序从其他机器的Excel或DBF文件中导入数据,我可以轻松读取字符串数据,但是无法正确读取数值数据,特别是价格列。源机器可能使用逗号作为小数分隔符或任何格式。

只有当数值的字符串格式与应用程序机器设置匹配时,decimal.Parse(...)或decimal.TryParse(...)才能正常工作。


2
“任何格式”?这包括精灵语吗? - Paul Draper
1
给我们列出可能的情况清单。但更有可能您想使用 CultureInfo.InvariantCulture 来以相同(中性)的方式处理所有数字。 - Sinatr
1
1,234.56 ___ 1,234.56 ___ 1 234,56 ___ 1.23 ___ 1,23 - user1104916
2个回答

4

当您调用 decimal.TryParsedecimal.Parse 时,您可以指定一种文化(从而避免仅获取系统设置)。您可以逐个尝试您感兴趣的每种文化,直到找到其中一个成功解析该值的文化。

bool decimal TryParseAllCultures(string text, out value)
{
    foreach (var culture in cultures)
    {
        if (decimal.TryParse(text, NumberStyles.Number, culture, out value))
        {
            return true;
        }
    }
    return false;
}

您需要决定支持哪些文化,并确定NumberStyles.Number是否是您感兴趣的NumberStyle

尽管如此,这样做非常危险。考虑“1,234”。在使用逗号作为千位分隔符的文化中,它可能意味着“一千零二十四”,而在使用逗号作为小数分隔符的文化中,它可能意味着“略小于一点二五”。如果您无法确定应该使用哪个值,您很容易犯错。如果您知道预期值的范围,则可以将其用作启发式信息来检查实际想要的值,但我仍然感到有点担心。


1,234.56 __ 1,234.56 __ 1 234,56 __ 1.23 __ 1,23 - user1104916
@user1104916:那么"1,234"算什么?考虑到它可能等于"1,234.00"?或者小数点后面总是有两个数字吗? - Jon Skeet
如果有小数点,只保留两位小数。 - user1104916
@user1104916:最麻烦的是“if any”。因为我怀疑在英语环境中,“1,23”会被解析为123。(它不会检查千位分隔符是否实际上处于正确的位置。) - Jon Skeet

0

这似乎可以工作

    public static char DecimalSeparator(string sValue)
    {
        var decimalPosition = sValue.Length - 4;
        if (decimalPosition < 0)
        {
            return '.';
        }
        var decimalPart = sValue.Substring(decimalPosition);
        if (decimalPart.Contains(','))
        {
            return ',';
        }
        return '.';
    }

    public static decimal StringToDecimal(string toParse)
    {
        if (string.IsNullOrEmpty(toParse))
        {
            return 0;
        }

        var stb = new StringBuilder();
        var localDecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray()[0];
        var sourceDecimalSeparator = DecimalSeparator(toParse);
        var sNumeric = "0123456789-" + sourceDecimalSeparator;

        for (var i = 0; i < toParse.Length; i++)
        {
            var currentChar = toParse[i];
            if (sNumeric.IndexOf(currentChar) > -1)
            {
                if (currentChar == sourceDecimalSeparator)
                {
                    currentChar = localDecimalSeparator;
                }
                stb.Append(currentChar);
            }
        }

        return decimal.Parse(stb.ToString());
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接