为什么 double.TryParse("0.0000", out doubleValue) 返回 false?

39
我正在尝试使用 double.TryParse() 解析字符串 "0.0000",但是不知道为什么它在这个特定的例子中返回 false。当我传递整数样式的字符串,例如 "5",它会正确解析为值 5。
有什么想法,为什么会出现这种情况?

8
考虑运行时的本地化设置...也许您正在运行一个使用逗号而不是点作为小数点的系统? - Yahia
2
@Yahia:建议您将其作为答案(并包括重载,以接受IFormatProvider,以便可以指定文化)。 - Richard
也许你选择了错误的文化。TryParse默认使用当前文化。(在我看来这是一个愚蠢的决定,但现在改变已经太晚了) - CodesInChaos
9个回答

66

代码在运行时会考虑本地化设置...也许你正在运行一个以逗号 , 作为小数点而非点 . 的系统上...

在您的情况下,我假设您希望使用固定的区域设置,无论您在哪个系统上运行,小数点都是 .:

double.TryParse("0.0000", NumberStyles.Number, CultureInfo.CreateSpecificCulture ("en-US"), out temp)

或者

double.TryParse("0.0000", NumberStyles.Number,CultureInfo.InvariantCulture, out temp)

以下是一些MSDN参考链接:


10

TryParse 默认使用当前区域设置。如果你的当前区域设置使用与 . 不同的小数分隔符,它将无法按照你的意图解析 0.0000。因此,你需要传递 CultureInfo.InvariantCulture

var numberStyle = NumberStyles.AllowLeadingWhite |
                 NumberStyles.AllowTrailingWhite |
                 NumberStyles.AllowLeadingSign |
                 NumberStyles.AllowDecimalPoint |
                 NumberStyles.AllowThousands |
                 NumberStyles.AllowExponent;//Choose what you need
double.TryParse( "0.0000", numberStyle, CultureInfo.InvariantCulture, out myVar)

3
几乎可以确定问题是Thread.CurrentCulture没有使用点作为小数分隔符。
如果您知道该数字将始终使用点作为小数分隔符,则使用此代码,该代码利用double.TryParse另一个重载
style = NumberStyles.Float | NumberStyles.AllowThousands;
culture = CultureInfo.InvariantCulture;
float num;
if (double.TryParse("0.0000", style, culture, out num)) {
    // whatever
}

2

如果当前文化中指定的小数点分隔符与.字符不同,则它将返回false

在解析字符串表示形式时,您需要注意它们所代表的文化,否则您将获得意外行为。

在这种情况下,您将得到false,但更糟糕的是,例如在以下示例中,如果您期望获得数字1,您将得到一千:

Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-PT");

double d;
Console.WriteLine(double.TryParse("1.000", out d));
Console.WriteLine(d);

这是因为在葡萄牙文(葡萄牙)的文化中,使用“.”字符作为“NumberGroupSeparator”,而使用“,”字符作为“NumberDecimalSeparator”。如果要解析用户输入,则始终使用与用户相关联的文化进行解析。获取用户关联的文化取决于上下文,例如,在Windows窗体应用程序中,您可以在UI线程上使用Thread.CurrentThread.CurrentCulture来获取它。在ASP.NET应用程序中可能会有所不同。

1

1

要将文化更改为使用“.”作为小数分隔符,请使用:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");

更改当前的区域设置有点麻烦。特别是因为你需要保存和恢复它。而且还要注意异常情况... - CodesInChaos
@CodeInChaos: 我在想也许他需要在整个应用程序范围内,或者至少在线程范围内以相同的方式解析双精度数。这样可以帮助他避免将文化传递给每个调用的解析方法。 - Tudor

0

使用 TryParse 更改 CultureInfo 对我没有任何作用。我必须在控制面板下更改数字格式(更改日期、时间或数字格式),并更改小数符号。然后它又可以工作了。


-2
关于这件事最愚蠢的是,它只接受“,”作为我的文化中的小数分隔符,但结果却是“.”。某个人,在某个地方,那天想得不太顺利...所以我会尝试这个:
if ((double.TryParse(sVat, out vat)) == false)
    if (double.TryParse(sVat.Replace(",", "."), out vat) == false)
      double.TryParse(sVat.Replace(".", ","), out vat);

1
"我会试试这个" 这是一个回答吗?它有效吗?如果无效,请说“我会试试这个”。 - Error - Syntactical Remorse

-3

对我来说它有效:

double temp = 0;
Console.WriteLine(double.TryParse("0.0000", out temp));
Console.ReadLine();

写入 True


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接