Double.TryParse 将 0.1 转换为 1.0

本文关键字:转换 TryParse Double | 更新日期: 2023-09-27 18:33:22

>情况 - 我的 Web 应用程序中的线程区域性已设置为"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);

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

Double.TryParse 将 0.1 转换为 1.0

你说"0.1"是西班牙语中的数字。其实不是,它是数字英文或其他东西

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"

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

'." - 解析时,将忽略"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 双精度,因为 '." as在 ES 文化中成为一千个分隔符将被忽略。您可以执行以下任一操作:

  1. 使用固定区域性而不是"es":

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

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

    var 编号西班牙语 = "0,1";

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

我终于能够确定出了什么问题。问题不在于 TryParse() 函数,而在于 ToString() 函数。

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

若要修复此问题,请改用 Convert.ToString 并传入区域性信息。

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

经验教训 - 在全球化应用程序中使用 ToString() 时要小心!