【问题标题】:parse decimal from string in any format从任何格式的字符串中解析十进制
【发布时间】:2013-11-11 16:46:33
【问题描述】:

下一个方法的任何实现:

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

我的应用程序从其他机器的 excel 或 dbf 文件导入数据,读取字符串数据没有问题,但我没有成功读取正确的数字数据,尤其是价格列。 源机器可以使用逗号作为小数分隔符或任何格式。

decimal.Parse(...) 或 decimal.TryParse(...) 仅当数值的字符串格式与应用机器设置匹配时才有效。

【问题讨论】:

  • “任何格式”?这包括精灵语吗?
  • 给我们一个可能的案例列表。但您更有可能希望使用CultureInfo.InvariantCulture 以相同(中立)的方式威胁所有号码。
  • 可能的格式:1 234.56 ___ 1,234.56 ___ 1 234,56 ___ 1.23 ___ 1,23

标签: c# parsing decimal


【解决方案1】:

当您调用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:那么“1,234”算什么?请记住它可能等于“1,234.00”?还是总是小数点后有两位数?
  • 小数点后两位数,如果有的话
  • @user1104916:“如果有的话”很痛苦。因为我怀疑“1,23”会在英语语言环境中被解析为 123。(它不会检查千位分隔符实际上是否在正确的位置。)
【解决方案2】:

这似乎有效

    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());
    }

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多