【问题标题】:Parsing decimal with thousands separator用千位分隔符解析十进制
【发布时间】:2015-03-19 14:26:52
【问题描述】:

我有以下代码块:

string price = "1,234.56";
decimal value = 0;
var allowedStyles = (NumberStyles.AllowDecimalPoint & NumberStyles.AllowThousands);

if (Decimal.TryParse(price, allowedStyles, CultureInfo.InvariantCulture, out value))
{
    Console.log("Thank you!");
}
else
{
    throw new InvalidFormatException();
}

最终,price 将采用美国风格(即 1,234.56)或德国风格(即 1.234,56)。我现在面临的挑战是,Decimal.TryParse 失败了。我怀疑它是因为千位分隔符。这就是我添加allowedStyles 变量的原因。

我做错了什么?

【问题讨论】:

  • 尝试传递CultureInfo.CurrentCulture 而不是InvariantCulture 作为第三个参数。这将使TryParse 适应当前机器的语言环境。
  • @CompuChip:我不太确定。通常使用InvariantCulture 是有意的。
  • 如果是解析币种,NumberStyles.Currency呢?
  • 您是从后端系统还是从用户获取输入?如果您从您控制的后端获取输入,您应该标准化单一格式——InvariantCulture 是一种合适的方式来做到这一点。如果您无法控制格式,希望有一些更高级别的协议可以让您知道您使用的是 DE 还是 US,否则您会有歧义(这些可以通过比 Decimal.Parse 接受的更严格的正则表达式来缓解可以选择合适的文化)。来自用户的输入应使用 CurrentCulture。

标签: c# globalization


【解决方案1】:

如果您AND-组合NumberStyles-标志,您将得到None

00100000 (AllowDecimalPoint)
&
01000000 (AllowThousands)
--------
00000000 (None)

尝试-组合它们:NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands

00100000 (AllowDecimalPoint)
|
01000000 (AllowThousands)
--------
01100000 (AllowDecimalPoint, AllowThousands)

另外,恐怕你不能用 one 语句解析 both 风格(美国风格和 DE 风格)。

所以我会尝试两个:

string price = "1,234.56";
decimal value = 0;
var allowedStyles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);

if (Decimal.TryParse(price, allowedStyles, CultureInfo.GetCultureInfo("DE-de"), out value))
{
    Console.Write("Danke!");
}
else if (Decimal.TryParse(price, allowedStyles, CultureInfo.GetCultureInfo("EN-us"), out value))
{
    Console.Write("Thank you!");
}
else
{
    throw new InvalidFormatException();
}

【讨论】:

  • 除非它实际上同时具有小数分隔符和千位分隔符,否则尝试解析两者时仍然模棱两可。 (12,34.56 仍会使用 en-US 解析,所以 12,34 1234 或 12.34 也是如此?)
  • 没错,如果你有像134.567 这样的数字,你就无法知道. 是千位分隔符还是小数分隔符。使用12,34.56 会更容易,因为在thisand 分隔符之前不能有小数点分隔符——所以, 在这种情况下必须是千位分隔符。不过,在某些情况下,您无法确定给出的样式。
【解决方案2】:

此二进制and (&) 的结果将始终为0false,或NumberStyles.None)。这就是为什么它不允许小数和千位分隔符:

var allowedStyles = (NumberStyles.AllowDecimalPoint & NumberStyles.AllowThousands);

改成二进制or|):

var allowedStyles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多