【问题标题】:C# decimal.Parse behaviourC# decimal.Parse 行为
【发布时间】:2011-01-13 08:27:02
【问题描述】:

小问题:

为什么这些“.....”对于在 .NET (C#) 中解析小数有效:

decimal res = decimal.Parse("8......15");  // returns 815
decimal res = decimal.Parse("8...15");     // returns 815
decimal res = decimal.Parse("8..15");      // returns 815

这是什么原因?

【问题讨论】:

  • 我已经在 .NET4.0 中检查过了。它引发格式异常
  • 您使用的是什么文化?无法使用我当前的文化或不变文化解析这些字符串。
  • 我认为这是程序员的懒惰。我还没有见过这么松散地使用千位分隔符的地方。
  • @Saeed:这取决于你所处的文化......
  • @Jon skeet,是的,我看到了你的好答案,并在我留下上述评论后投票赞成。

标签: c# parsing decimal


【解决方案1】:

对我来说失败了。你有没有机会在“。”的文化中。是千位分隔符,“,”是小数点吗? Decimal.Parse(和类似的调用)默认使用线程的当前文化。这是否是一件好事是有争议的,但与实际行为无关:)

尝试在decimal.Parse 调用中指定CultureInfo.InvariantCulture

decimal res = decimal.Parse("8......15", CultureInfo.InvariantCulture);

我相信这会如你所愿。

【讨论】:

  • 我想你已经一针见血了。例如,如果您使用 de-DE 文化,它会正确解析。
  • es-ES 到。多么奇怪的文化
  • 确实如此。我的 CurrentCulture 是 "nl-BE",NumberDecimalSeparator = "," 和 NumberGroupSeparator = "."谢谢!但是他们允许这样的符号是相当奇怪的。
  • @juFo:支持多个连续组分隔符确实很奇怪。我敢说这是有原因的:)
  • @Jon Skeet(上面的回复)如果有人知道允许或支持它的确切原因会很好(我指的是多个连续的组分隔符)。
【解决方案2】:

我想这是因为解析器实际上并不关心组分隔符 - 它们与将字符串转换为小数的过程无关。

我们称它们为千位分隔符,但实际上并非如此。它们是组分隔符 - 您可以每 3 位数、每 10 位数、每 1 位数拆分,那么为什么不每 0 位数?

有趣的是,.NET 4 的代码已更改 - 这是 Reflector 对我而言的相关输出:

else
{
    if (((currencySymbol == null) || 
         ((chPtr2 = MatchChars(p, currencySymbol)) == null)) && 
        ((ansiCurrencySymbol == null) || 
         ((chPtr2 = MatchChars(p, ansiCurrencySymbol)) == null)))
    {
        break;
    }
    num |= 0x20;
    currencySymbol = null;
    ansiCurrencySymbol = null;
    p = chPtr2 - 1;
}

【讨论】:

    【解决方案3】:

    我不知道为什么,但我知道它是如何工作的(十进制解析器代码部分见下文)。如果只是打开点标志并跳过所有点,我认为最后一个。

        while (true)
    {
        if (((ch >= '0') && (ch <= '9')) || (((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None) && (((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F')))))
        {
            //Here goes some code...
        }
        else if ((((options & NumberStyles.AllowDecimalPoint) != NumberStyles.None) && ((num & 0x10) == 0)) 
        && (((chPtr2 = MatchChars(p, currencyDecimalSeparator)) != null) || ((flag && ((num & 0x20) == 0)) 
        && ((chPtr2 = MatchChars(p, numberDecimalSeparator)) != null))))
        {
            num |= 0x10;
            p = chPtr2 - 1;
        }
    }
    

    使用 Reflector 工具调查所有代码。

    【讨论】:

    • 有趣!很高兴看到有关 HexSpecifier 的部分代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 2015-04-24
    • 2013-11-08
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多