将货币字符串转换为十进制?

Posted

技术标签:

【中文标题】将货币字符串转换为十进制?【英文标题】:Convert currency string to decimal? 【发布时间】:2012-12-19 04:47:09 【问题描述】:

目标

string 进行排序,该string 在一组数据中以数字形式显示类似$1,995.94 的货币数据。

代码

我目前正在使用下面的代码示例将string 值转换为decimal,以便我可以对其进行正确排序。

if (sortBy == "checkAmount")

    StringBuilder sb = new StringBuilder();
    foreach (var c in Convert.ToString(p.GetType().GetProperty(sortBy).GetValue(p, null)))
    
        if (!char.IsDigit(c) && c != '.')  continue; 
        sb.Append(c);
    
    return Convert.ToDecimal(sb.ToString());

else

    return p.GetType().GetProperty(sortBy).GetValue(p, null);

问题

有什么更好的方法来做到这一点?它有效,这很酷,但它不是很优雅。

最终解决方案

answer provided by Servy 按预期工作,我使用该实现有一段时间了,但我和一位同事找到了更好的方法,所以我在这里记录它。 顺便说一句,我最终还是使用了这个解决方案。

decimal.Parse(input, NumberStyles.AllowCurrencySymbol | NumberStyles.Number);

【问题讨论】:

首先,将字符串解析从业务逻辑中分离出来。有一个方法 ParseString 接受 string 并返回 decimal 而不是将它与一堆逻辑混合以获取要解析的字符串。接下来,您可以使用正则表达式,例如 ^[\d.]+(未经测试)而不是循环。 哦,既然你有“工作”代码,这可能应该在代码审查中,而不是 SO。 @Servy,我正在研究那个正则表达式。 @Servy,我得到了这个工作[-\d.]+,但是- 会引起问题吗?我只是想确保我得到负数。我意识到我错过了当前算法中的那些。 @Servy,请查看我的更新。我将您的答案保留为已接受的答案,但我和一位同事找到了更好的方法。看看吧。 【参考方案1】:

这个怎么样,但只适用于一个字符串值。因此,您需要通过$ 获取您的字符串split,然后在保存到arraylist 的同时进行转换

 using System.Globalization;
    //rest of your code

          string str = "$50,550.20";
          decimal decval;
          bool convt = decimal.TryParse(str, NumberStyles.Currency,
            CultureInfo.CurrentCulture.NumberFormat, out decval);
          if (convt) 
          Console.WriteLine(decval);
          Console.ReadLine();

【讨论】:

见my other comment here。您的代码会说如果在字符串末尾给出无效字符,则它无法产生有效值,他的代码会尝试获取尽可能多的数字。即使不需要,那也不是等效的代码。 感谢@Servy 显示缺陷,非常感谢。阅读您的评论。 @bonCodigo 你真的找到了处理货币的正确方法。虽然它没有完全模仿 OPs 方法,但它显示了正确的方法。 OP 示例“接受”格式错误的货币值,例如 $1995.,94,甚至是 $abc.123,456。没有标准方法可以将这些字符串解释为数字,这就是为什么有一个内置的货币解析标准。 +1 @NominSim 感谢您提供的示例非常有帮助。 :) 我的理解是 OP 有一个字符串,例如$1,234.50$23456.99 $345.88 等等.. 但我意识到 regex 将删除包括“$”在内的数字 . 然后转换为 decimal 使用此解决方案引用特定的文化格式。外汇。 bool convt = decimal.TryParse(amount, NumberStyles.Currency, CultureInfo.CreateSpecificCulture("da-DK").NumberFormat, out decimal decval);【参考方案2】:

这是一个更简单的解决方案:

    public static decimal ToDecimal(this string str)
    
        return decimal.Parse(str, NumberStyles.Currency);
    

和单元测试:

    [Test]
    public void ToDecimal_Convert_String_To_Decimal()
    
        Assert.AreEqual(1234M, "1234".ToDecimal());
        Assert.AreEqual(-1234.56M, "$(1,234.56)".ToDecimal());
        Assert.AreEqual(1234.56M, "$1,234.56".ToDecimal());
    

【讨论】:

比 Regex 更优化,但与 CurrentCulture 以外的其他货币符号不兼容。【参考方案3】:

这是一个与您提供的代码最相似的方法

public static decimal Parse(string input)

    return decimal.Parse(Regex.Replace(input, @"[^\d.]", ""));

这是一个支持负数的选项,如果找到第二个句点值,它将停止,从而减少它返回的无效decimal 值的字符串数量。它还有一些其他在 OP 中看不到的修改,以处理当前代码没有的其他情况。

public static decimal Parse(string input)

    return decimal.Parse(Regex.Match(input, @"-?\d1,3(,\d3)*(\.\d+)?").Value);

【讨论】:

当心这个解决方案,尤其是第二部分。它不能处理所有情况,如果输入为 -5000 则计算结果为 -500,则会出现严重错误。【参考方案4】:
decimal amount = decimal.Parse("$123,456.78",
NumberStyles.AllowCurrencySymbol |
NumberStyles.AllowThousands |
NumberStyles.AllowDecimalPoint);

【讨论】:

解释你的答案的要素以及为什么它更好、更优雅会让这个答案成为一个很好的答案。【参考方案5】:

适用于所有文化:

var d = decimal.Parse("$497.7", NumberStyles.Currency, CultureInfo.CreateSpecificCulture("us-US").NumberFormat);    

Console.WriteLine(d);

【讨论】:

【参考方案6】:
public static decimal ToDecimalFromStringDecimalOrMoneyFormattedDecimal(this string s)

    try
    
        return decimal.Parse(s);
    
    catch
    
        var numberWithoutMoneyFormatting = Regex.Replace(s, @"[^\d.-]", "");
        return decimal.Parse(numberWithoutMoneyFormatting);
    


[Test]
public void Test_ToDecimalFromStringDecimalOrMoneyFormattedDecimal()

    Assert.That("$ 500".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)500);
    Assert.That("R -500".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)-500);
    Assert.That("-$ 500".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)-500);
    Assert.That("P 500.90".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)500.9);
    Assert.That("$ -50 0,090,08.08".ToDecimalFromStringDecimalOrMoneyFormattedDecimal() == (decimal)-50009008.08);

【讨论】:

以上是关于将货币字符串转换为十进制?的主要内容,如果未能解决你的问题,请参考以下文章

将 JavaScript 字符串变量转换为小数/货币

通过jquery将货币转换为小数

将十进制转换为小数点后两个零的字符串,和逗号? C# [重复]

.Net:使用 String.Replace 将货币格式的值转换为十进制值

将货币字符串转换为数字 Drupal Views / PHP

如何使用 Javascript 将货币字符串转换为双精度?