【问题标题】:Double.TryParse converts 0.1 to 1.0Double.TryParse 将 0.1 转换为 1.0
【发布时间】:2013-09-30 11:46:52
【问题描述】:

情况 - 我的网络应用程序中的线程文化已设置为“es”(西班牙语)

Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("es");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("es");

字符串值为“0.1” 对于以下表达式,

var value = "0.1"
provider = CultureInfo.CreateSpecificCulture("en-US")
double.TryParse(value.ToString(), NumberStyles.Any, provider, out number)

数字返回 1.0。这让我觉得它正在从线程中挑选文化信息。不是我提供的。

以下单元测试通过(如预期)。

var numberInEnUS = "0.1";
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
culture = new CultureInfo("en-US", false);
Thread.CurrentThread.CurrentCulture = spanishCulture;
Thread.CurrentThread.CurrentUICulture = spanishCulture;
double number;
double.TryParse(numberInEnUs, NumberStyles.Any, culture, out number);
Assert.AreEqual(0.1, number);

那么,问题是为什么 double.TryParse 在我的应用程序中失败了?理论上,西班牙语的 0.1 是 1(西班牙语的分隔符是小数点“.”)。但是,数字 1000.0 不会转换为 10000。所以,它似乎只对 0.1 失败 任何解释都非常感谢!

【问题讨论】:

  • 只要您将特定的文化传递给double.TryParse(),线程的文化应该是无关紧要的。我注意到您没有包含设置提供程序变量的代码;您是否 100% 确定要发送您认为要发送的提供商?顺便说一句,使用 CultureInfo.InvariantCulture 可能比使用“en-US”更好,尽管它对您的情况没有影响。
  • provider 指的是什么?这是最关键的部分,但它缺失了。
  • 其实数字是英文的……我改了上面的。

标签: c# globalization cultureinfo tryparse


【解决方案1】:

您说“0.1”是西班牙语中的数字。其实不是,是numberInEnglish什么的

var numberInSpanish = "0.1";//this is number in english culture

应该是

var numberInSpanish = "0,1";//<--Note 0,1

NumberDecimalSeparator 西班牙语是,。解析0,1你会得到预期的结果。

var numberInSpanish = "0,1";
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
var culture = new CultureInfo("en-US", false);
Thread.CurrentThread.CurrentCulture = spanishCulture;
Thread.CurrentThread.CurrentUICulture = spanishCulture;
double number;
double.TryParse(numberInSpanish, NumberStyles.Any, spanishCulture, out number);

这里number被正确解析为“0.1”

【讨论】:

    【解决方案2】:

    您的问题在于小数和千位分隔符的混合,即:

    '.' - "es" 文化中的千位分隔符,在解析时将被忽略(例如 1.000,0 == 1000,0)

    ',' - "es" 文化中的小数分隔符,分隔整数和小数部分

    你可以轻松说服自己:

      var spanishCulture = CultureInfo.CreateSpecificCulture("es");
      Char dS = spanishCulture.NumberFormat.NumberDecimalSeparator; // <- ','
      Char tS = spanishCulture.NumberFormat.NumberGroupSeparator;   // <- '.' 
    

    因此,在您的情况下,字符串“0.1”将转换为 1.0 double,因为 '.'作为 在 es 文化中作为千位分隔符将被忽略。 你可以这样做:

    1. 使用不变文化代替“es”之一:

      double.TryParse(numberInNeutral, NumberStyles.Any, CultureInfo.InvariantCulture, out number);

    2. 或者使用实际的西班牙数字表示

      var numberInSpanish = "0,1";

      double.TryParse(numberInSpanish, NumberStyles.Any,culture, out number);

    【讨论】:

    • 我尝试过使用 InvariantCulture,但值仍然是 1.0。它似乎总是选择线程文化。
    【解决方案3】:

    我终于能够找出问题所在。问题不在于 TryParse() 函数,而在于 ToString() 函数。

    该值实际上是一个 Double 类型,而不是我上面提到的字符串。 (我的错,我认为这无关紧要)。我实际上是在做一个 value.ToString()。这是它使用线程文化并更改值的地方。 因此,如果值为 0.1,则 value.ToString() 将其更改为“0,1”。它会根据线程文化自动更改十进制字符。 TryParse 然后使用 en-US 区域性并将“0,1”转换为 1。

    要修复它,请改用 Convert.ToString 并传入文化信息。

    最后,这只是一个愚蠢的错误。

    LessonLearnt - 在全球化应用程序中使用 ToString() 时要小心!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多