使用货币符号解析数值

3

我查看了多个关于解析货币的stackoverflow问题,最好(推荐)的方法似乎是我下面尝试的方法:

var payout = decimal.Parse("$2.10", NumberStyles.Currency | NumberStyles.AllowDecimalPoint);

然而,它抛出异常:输入字符串格式不正确。
我不知道我做错了什么?
编辑
感谢回答。额外信息:我给出的硬编码货币值只是一个例子。我有一个货币列表:
€2,66 $2.10 $5.55 等等。
我无法提前确定文化信息。有什么想法吗?

3
搬到另一个使用 $ 作为货币符号和 . 作为小数分隔符的国家。或者阅读有关 "CultureInfo" 的信息,可能更便宜。 - undefined
货币字符串将是动态的,不像我的示例一样硬编码。例如 $2.10、€2,66 等等。我如何提前知道 CultureInfo 呢? - undefined
逃离吧... 没有对于格式化该值所使用的CultureInfo的了解,就没有办法正确解析$3,100。检查所有货币符号并希望你猜对了小数分隔符是最安全的选择(我不建议你冒这个险)。 - undefined
5个回答

2
您可以尝试这样做:

您可以尝试以下方法:

decimal currencyValue;
string inputCurrency = "$12.6";
if (decimal.TryParse(inputCurrency, NumberStyles.Currency, CultureInfo.CreateSpecificCulture("en-US"), out currencyValue))
  {
      // proceed with currencyValue
  }
else 
  {
      //Show error ; Conversion failed
  }

要处理所有货币,您可以使用以下方法:

        Dictionary<char, string> currencyCulture = new Dictionary<char, string>();
        currencyCulture.Add('$', "en-US");
        currencyCulture.Add('€', "en-IE");
        // populate all posible values here
        decimal currencyValue;
        string inputCurrency = "€2,66";
        char currencySymbol= inputCurrency.ToCharArray()[0];
        CultureInfo currentCulture= CultureInfo.CreateSpecificCulture(currencyCulture[currencySymbol]);
        if (decimal.TryParse(inputCurrency, NumberStyles.Currency, currentCulture, out currencyValue))
        {
            // proceed with currencyValue
        }
        else 
        {
         //Show error ; Conversion failed
        }

您可以从这里选择文化名称。

2

@un-lucky提到的解决方法类似,我试着将其泛化并使其适用于每一个符号/格式

public static decimal ParseCurrencyWithSymbol(string input)
{
    var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures)
        .GroupBy(c=> c.NumberFormat.CurrencySymbol)
        .ToDictionary(c=> c.Key, c=>c.First());


    var culture = cultures.FirstOrDefault(c=>input.Contains(c.Key));

    decimal result = 0;
    if(!culture.Equals(default(KeyValuePair<string,CultureInfo>)))
    {
        result = decimal.Parse(input, NumberStyles.Currency | NumberStyles.AllowDecimalPoint, culture.Value);
    }
    else
    {
        if( !decimal.TryParse(input, out result))
        {
            throw new Exception("Invalid number format");
        }
    }

    return result;
}

用法

decimal output = ParseCurrencyWithSymbol("$2.10");

工作中的代码


使用欧元,您的代码输出为210,这是错误的,因为在欧盟中,“逗号”是小数分隔符,而不是“句点”。 - undefined
@l3utterfly 啊.. 没注意到,谢谢指出。会修复的。 - undefined
@l3utterfly修复了它。 - undefined
谢谢,我使用了一个非常类似的实现,基于你的答案,尽管我没有想到使用AllCultures和按货币符号分组。谢谢! - undefined
仍然不正确,如果您有两个相同的货币符号,但小数点表示法不同,您可能会使用错误的表示法。荷兰公民会写成:€ 4000,32,而美国公民在谈论在荷兰投资资金时会写成 € 4,000.32。 - undefined

0

如何使用一个 CleanCurrency 方法呢?

/// Loops each char in the string and returns only numbers, . or ,
static double? CleanCurrency(string currencyStringIn) {
  string temp = "";
  int n;
  for (int i = 0; i < currencyStringIn.Length; i++) {
    string c = currencyStringIn.Substring(i, 1);
    if (int.TryParse(c, out n) || c == "." || c == ",") {
      temp += c;
    }
  }
  if (temp == "") {
    return null;
  else {
    return double.Parse("0" + temp);
  }
}

这里的想法是只获取一个实际的数字,而不管字符串内容是什么。

double? payout = CleanCurrency("$3.50");

这是关于什么的呢?这里的问题在于"1,500"和"1.500"是完全不同的值 - 没有解释你的代码如何解决这个问题(除了使用非常复杂的Regex.Replace("$1.2", @"[^\d,\.]","")实现之外)。 - undefined

0
我已经对Hari Prasad的回答进行了详细阐述。通过这个方法,你可以最小化文化结果。在你的应用程序中更新"SupportedCultures",添加你可能会使用的语言。
    private static readonly List<string> SupportedCultures = new List<string> {"en-US", "en-GB", "fr-FR"};

    public static void Main()
    {
        var (amount, culture) = ParseCurrencyWithSymbol("$256.12");
        Console.WriteLine($"{culture?.Name} | {amount}");

        var (amount2, culture2) = ParseCurrencyWithSymbol("£389.17");
        Console.WriteLine($"{culture2?.Name} | {amount2}");

        var (amount3, culture3) = ParseCurrencyWithSymbol("€421,10");
        Console.WriteLine(culture3 != null ? $"{culture3.Name} | {amount3}" : "Failed!");
    }

    public static Tuple<decimal?, CultureInfo> ParseCurrencyWithSymbol(string input)
    {
        var culture = CultureInfo.GetCultures(CultureTypes.AllCultures)
            .Where(x => SupportedCultures.Contains(x.Name))
            .FirstOrDefault(c => input.Contains(c.NumberFormat.CurrencySymbol));

        if (culture == null) return new Tuple<decimal?, CultureInfo>(null, null);

        return new Tuple<decimal?, CultureInfo>(decimal.Parse(input,
            NumberStyles.Currency | NumberStyles.AllowCurrencySymbol |
            NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, culture), culture);
    }

-1
适用于您特定情况的代码片段如下:
var payout = decimal.Parse("$2.10".Replace("$",""));

如果你不知道货币符号是什么,那么可以尝试以下解决方案:
string _money = "$2.10";
var payout = decimal.Parse(_money.Substring(1));

处理逗号和小数点要困难得多:如果这是问题,可以参考成员@un-lucky提供的解决方案。
希望这能有所帮助。

真的没有什么能帮到楼主的东西 :) ... 尤其是这段代码,因为并不是每个地方都在前面放置货币符号。 - undefined
@AlexeiLevenkov 是的,我同意。这个问题太广泛了,有太多的不确定性。祝好! - undefined

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