C# 使用货币符号分析值

C# 使用货币符号分析值,c#,.net,parsing,C#,.net,Parsing,我已经研究了多个关于解析货币的SO问题,最好的(推荐的)方法似乎是我正在尝试的以下方法: var payout = decimal.Parse("$2.10", NumberStyles.Currency | NumberStyles.AllowDecimalPoint); 但是,它会引发异常:输入字符串的格式不正确 我不知道我做错了什么 编辑 谢谢你的回答。附加信息:我给出的硬编码货币值只是一个例子。我有一份货币清单: 2,66欧元 2.10美元 5.55美元 等等 我无法预先确定文化信息。

我已经研究了多个关于解析货币的SO问题,最好的(推荐的)方法似乎是我正在尝试的以下方法:

var payout = decimal.Parse("$2.10", NumberStyles.Currency | NumberStyles.AllowDecimalPoint);
但是,它会引发异常:输入字符串的格式不正确

我不知道我做错了什么

编辑

谢谢你的回答。附加信息:我给出的硬编码货币值只是一个例子。我有一份货币清单:

2,66欧元

2.10美元

5.55美元

等等


我无法预先确定文化信息。有什么想法吗?

与您的具体情况相关,您可以使用以下代码段:

var payout = decimal.Parse("$2.10".Replace("$",""));
如果您不知道货币符号是什么,请尝试以下解决方案:

string _money = "$2.10";
var payout = decimal.Parse(_money.Substring(1));
处理逗号和小数点要困难得多:如果这是一个问题,请参考成员@un lucky给出的解决方案

希望这能有所帮助。

您可以这样尝试:

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
        }
Dictionary currencyCulture=new Dictionary();
添加(“$”,“en US”);
货币文化。添加(“€”和“en-IE”);
//在此处填充所有可能的值
十进制货币值;
字符串inputCurrency=“€2,66”;
char currencySymbol=inputCurrency.ToCharArray()[0];
CultureInfo currentCulture=CultureInfo.CreateSpecificCulture(currencyCulture[currencySymbol]);
if(decimal.TryParse(inputCurrency、NumberStyles.Currency、currentCulture、OutCurrencyValue))
{
//继续使用currencyValue
}
其他的
{
//显示错误;转换失败
}

您可以从中选择区域性名称
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);
  }
}

类似的方法@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;
}

工作

我已经详细阐述了哈里·普拉萨德的答案。有了它,您可以最小化培养结果。将“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);
    }
private static readonly List SupportedCultures=新列表{“en-US”、“en-GB”、“fr-fr”};
公共静态void Main()
{
var(金额、文化)=ParseCurrencyWithSymbol($256.12”);
Console.WriteLine($“{culture?.Name}{amount}”);
var(数量2,文化2)=使用符号(“389.17英镑”);
Console.WriteLine($“{culture2?.Name}{amount2}”);
var(金额3,文化3)=带有符号的分析货币(“421,10欧元”);
Console.WriteLine(culture3!=null?$“{culture3.Name}{amount3}”:“失败!”;
}
公共静态元组ParseCurrencyWithSymbol(字符串输入)
{
var culture=CultureInfo.GetCultures(CultureTypes.AllCultures)
.Where(x=>SupportedCultures.Contains(x.Name))
.FirstOrDefault(c=>input.Contains(c.NumberFormat.CurrencySymbol));
if(culture==null)返回新的元组(null,null);
返回新元组(decimal.Parse)(输入,
NumberStyles.Currency | NumberStyles.AllowCurrencySymbol|
NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands,culture),culture);
}

移动到另一个国家(使用美元作为货币符号,
作为十进制分隔符的国家)。或者阅读
CultureInfo
,因为它可能更便宜。货币字符串将是动态的,而不是像我的示例那样硬编码。例如:2.10美元、2.66欧元等。我如何提前知道文化信息?逃跑。。。如果不知道用于格式化值的CultureInfo,就无法正确解析$3100。检查所有货币符号的列表,并希望您猜对了小数点分隔符是最安全的赌注(我不建议这样下注)。这真的没有什么可以帮助OP:)。。。尤其是这个代码,因为不是每个地方都把货币符号放在前面。@AlexeiLevenkov是的,我同意。这个问题涉及面太广,不确定性太多。你好,怎么样?这里的想法是“1500”和“1.500”是非常不同的值-没有解释你的代码如何解决这个问题(除了一些非常复杂的
Regex.Replace(“$1.2”、@“[^\d,\.]”、“)
)用欧元,你的代码输出210,这是错误的,在欧盟,“逗号”是十进制分隔符,而不是“句点”@我要飞啊。。没有注意到,谢谢指点。将修复它。@l3utterfly修复了它。谢谢,根据您的回答,我使用了一个非常类似的实现,尽管我不认为使用所有文化和按货币符号分组。谢谢仍然不正确,如果您有两个相同的货币符号,使用不同的小数点符号,则可能使用不正确的符号。荷兰公民会写:4000,32欧元,而美国公民如果谈论在荷兰投资,会写4000.32欧元
decimal output = ParseCurrencyWithSymbol("$2.10");
    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);
    }