将货币字符串转换为十进制?
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
,然后在保存到array
或list
的同时进行转换
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);
【讨论】:
以上是关于将货币字符串转换为十进制?的主要内容,如果未能解决你的问题,请参考以下文章
将十进制转换为小数点后两个零的字符串,和逗号? C# [重复]
.Net:使用 String.Replace 将货币格式的值转换为十进制值