【问题标题】:How to convert string to double with proper cultureinfo如何使用适当的文化信息将字符串转换为双精度
【发布时间】:2010-04-06 07:49:24
【问题描述】:

我在数据库中有两个 nvarchar 字段来存储 DataType 和 DefaultValue,我有一个 DataType Double 和值为 65.89875 的英文格式。

现在我希望用户根据选择的浏览器语言格式查看值(英语中的 65.89875 应显示为德语中的 65,89875)。现在,如果用户从德语格式编辑为 65,89875,相当于英语中的 65.89875,而其他用户从英文浏览器查看,则为 6589875。

发生这种情况是因为在数据库中,它在 nvarchar 列中存储为 65,89875,当使用英语文化转换时,它变为 6589875,因为它将, 视为分隔符,这是德语的小数运算符。

如何让它适用于所有浏览器?

【问题讨论】:

  • 为什么将数字存储为文本开头?如果您可以更改架构,我强烈建议您这样做。

标签: c# .net localization globalization


【解决方案1】:

您需要为存储在数据库中的数据定义一个区域设置,不变的文化正是为此目的。

当您显示转换为本机类型,然后为用户的文化格式化。

例如显示:

string fromDb = "123.56";
string display = double.Parse(fromDb, CultureInfo.InvariantCulture).ToString(userCulture);

存储:

string fromUser = "132,56";
double value;
// Probably want to use a more specific NumberStyles selection here.
if (!double.TryParse(fromUser, NumberStyles.Any, userCulture, out value)) {
  // Error...
}
string forDB = value.ToString(CultureInfo.InvariantCulture);

PS。几乎不用说,使用具有与数据匹配的数据类型的列会更好(但有时也适用于旧版)。

【讨论】:

  • double.TryParse() 甚至没有文化参数...这个答案对我没有帮助;/
  • @sLw CultureInfo 实现 IFormatProvider: that overload 允许您传递所需的语言环境。但是 - 5 年来 - 这一直坐在这里,第二个和第三个论点颠倒(更正)!
【解决方案2】:

您可以将您的 UI 文化更改为您想要的任何内容,但您应该像这样更改数字分隔符:

CultureInfo info = new CultureInfo("fa-IR");
info.NumberFormat.NumberDecimalSeparator = ".";
Thread.CurrentThread.CurrentCulture = info;
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

有了这个,你的字符串转换如下:“12.49”而不是“12,49”或“12/49”

【讨论】:

    【解决方案3】:

    Convert.ToDouble(x) 还可以有第二个参数,指示 CultureInfo 以及何时将其设置为 System.Globalization.CultureInfo InvariantCulture 结果总是一样的。

    【讨论】:

      【解决方案4】:

      我从 MSDN 获得了一些帮助,但这是我的答案:

      double number;
      string localStringNumber;
      string doubleNumericValueasString = "65.89875";
      System.Globalization.NumberStyles style = System.Globalization.NumberStyles.AllowDecimalPoint;
      
      if (double.TryParse(doubleNumericValueasString, style, System.Globalization.CultureInfo.InvariantCulture, out number))
          Console.WriteLine("Converted '{0}' to {1}.", doubleNumericValueasString, number);
      else
          Console.WriteLine("Unable to convert '{0}'.", doubleNumericValueasString);
      localStringNumber =number.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("de-DE"));
      

      【讨论】:

        【解决方案5】:

        您可以借助FormatProviders 将用户提供的值转换为双精度值并将其再次存储为nvarchar。 CultureInfo 是一个典型的 FormatProvider。假设您了解您所经营的文化,

        System.Globalization.CultureInfo EnglishCulture = new System.Globalization.CultureInfo("en-EN");
        System.Globalization.CultureInfo GermanCulture = new System.Globalization.CultureInfo("de-de");
        

        足以进行必要的转换,例如;

        double val;
        if(double.TryParse("65,89875", System.Globalization.NumberStyles.Float, GermanCulture,  out val))
        {
            string valInGermanFormat = val.ToString(GermanCulture);
            string valInEnglishFormat = val.ToString(EnglishCulture);
        }
        
        if(double.TryParse("65.89875", System.Globalization.NumberStyles.Float, EnglishCulture,  out val))
        {
            string valInGermanFormat = val.ToString(GermanCulture);
            string valInEnglishFormat = val.ToString(EnglishCulture);
        }
        

        【讨论】:

        • @Richard,我已经找过了,但没找到,谢谢。
        【解决方案6】:

        使用不变文化。小数点分隔符始终为“.”最终您可以将“,”替换为“。” 当您显示结果时,请使用您当地的文化。但在内部使用始终不变的文化

        TryParse 并不总是像我们预期的那样工作在这个区域的 .net 中有更改请求:

        https://github.com/dotnet/runtime/issues/25868

        【讨论】:

          【解决方案7】:

          几年前我的工具带中就有这个函数(所有函数和变量名都很乱,西班牙语和英语混在一起,很抱歉)。

          它允许用户使用,. 来分隔小数,如果同时使用这两个符号会尽量做到最好。

              Public Shared Function TryCDec(ByVal texto As String, Optional ByVal DefaultValue As Decimal = 0) As Decimal
          
                  If String.IsNullOrEmpty(texto) Then
                      Return DefaultValue
                  End If
          
                  Dim CurAsTexto As String = texto.Trim.Replace("$", "").Replace(" ", "")
          
                  ''// You can probably use a more modern way to find out the
                  ''// System current locale, this function was done long time ago
                  Dim SepDecimal As String, SepMiles As String
                  If CDbl("3,24") = 324 Then
                      SepDecimal = "."
                      SepMiles = ","
                  Else
                      SepDecimal = ","
                      SepMiles = "."
                  End If
          
                  If InStr(CurAsTexto, SepDecimal) > 0 Then
                      If InStr(CurAsTexto, SepMiles) > 0 Then
                          ''//both symbols was used find out what was correct
                          If InStr(CurAsTexto, SepDecimal) > InStr(CurAsTexto, SepMiles) Then
                              ''// The usage was correct, but get rid of thousand separator
                              CurAsTexto = Replace(CurAsTexto, SepMiles, "")
                          Else
                              ''// The usage was incorrect, but get rid of decimal separator and then replace it
                              CurAsTexto = Replace(CurAsTexto, SepDecimal, "")
                              CurAsTexto = Replace(CurAsTexto, SepMiles, SepDecimal)
                          End If
                      End If
                  Else
                      CurAsTexto = Replace(CurAsTexto, SepMiles, SepDecimal)
                  End If
                  ''// At last we try to tryParse, just in case
                  Dim retval As Decimal = DefaultValue
                  Decimal.TryParse(CurAsTexto, retval)
                  Return retval
              End Function
          

          【讨论】:

            猜你喜欢
            • 2022-01-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-11
            • 1970-01-01
            相关资源
            最近更新 更多