将字符串转换为小数分隔符的最佳方法“。”和“,”不敏感的方式?

应用程序处理表示来自不同文化的小数的字符串。 例如,“1.1和”1,1“是相同的值。

我玩Decimal.TryParse标志组合,但无法达到我想要的结果。 “1,1”毕竟变为“11”或“0”。

是否可以在一行代码中将这些字符串转换为十进制而不预先将“,”char替换为“。” 或者使用NumberFormat.NumberDecimalSeparator

你是如何处理这种情况的?

先感谢您!

您有以下可能性:

  1. 你了解文化
    1. 使用当前的“文化”设置,为其安装计算机
    2. 您让用户决定在您的程序中设置他的文化 – >用户设置
  2. 你不懂文化
    1. 您必须做出决定:您必须定义并记录您的决定
    2. 猜猜:你试图解析,并尝试解析,并尝试…直到你得到有效的数字

您可以创建在解析时使用的临时CultureInfo对象。

 // get a temporary culture (clone) to modify var ci = CultureInfo.InvariantCulture.Clone() as CultureInfo; ci.NumberFormat.NumberDecimalSeparator = ","; decimal number = decimal.Parse("1,1", ci); // 1.1 

我发现了另一种方法。 它看起来很奇怪但它对我来说很好。

因此,如果您不了解目标系统的文化,并且您不知道您将获得12.33或12,33的值,您可以执行以下操作

 string amount = "12.33"; // or ie string amount = "12,33"; var c = System.Threading.Thread.CurrentThread.CurrentCulture; var s = c.NumberFormat.CurrencyDecimalSeparator; amount = amount.Replace(",", s); amount = amount.Replace(".", s); decimal transactionAmount = Convert.ToDecimal(amount); 

在调用Parse ,您只需要拥有正确的文化集,如下所示:

 string s = "11,20"; decimal c1 = decimal.Parse(s, new CultureInfo("fr-FR")); decimal c2 = decimal.Parse(s, new CultureInfo("en-AU")); Console.WriteLine(c1); Console.WriteLine(c2); 

以下是我的实施,任何好的想法?

 ///  /// ///  public static class NumberExtensions { ///  /// Convert string value to decimal ignore the culture. ///  /// The value. /// Decimal value. public static decimal ToDecimal ( this string value ) { decimal number; string tempValue = value; var punctuation = value.Where ( x => char.IsPunctuation ( x ) ).Distinct ( ); int count = punctuation.Count ( ); NumberFormatInfo format = CultureInfo.InvariantCulture.NumberFormat; switch ( count ) { case 0: break; case 1: tempValue = value.Replace ( ",", "." ); break; case 2: if ( punctuation.ElementAt ( 0 ) == '.' ) tempValue = value.SwapChar ( '.', ',' ); break; default: throw new InvalidCastException ( ); } number = decimal.Parse ( tempValue, format ); return number; } ///  /// Swaps the char. ///  /// The value. /// From. /// To. ///  public static string SwapChar ( this string value, char from, char to ) { if ( value == null ) throw new ArgumentNullException ( "value" ); StringBuilder builder = new StringBuilder ( ); foreach ( var item in value ) { char c = item; if ( c == from ) c = to; else if ( c == to ) c = from; builder.Append ( c ); } return builder.ToString ( ); } } [TestClass] public class NumberTest { ///  /// ///  [TestMethod] public void Convert_To_Decimal_Test ( ) { string v1 = "123.4"; string v2 = "123,4"; string v3 = "1,234.5"; string v4 = "1.234,5"; string v5 = "123"; string v6 = "1,234,567.89"; string v7 = "1.234.567,89"; decimal a1 = v1.ToDecimal ( ); decimal a2 = v2.ToDecimal ( ); decimal a3 = v3.ToDecimal ( ); decimal a4 = v4.ToDecimal ( ); decimal a5 = v5.ToDecimal ( ); decimal a6 = v6.ToDecimal ( ); decimal a7 = v7.ToDecimal ( ); Assert.AreEqual ( ( decimal ) 123.4, a1 ); Assert.AreEqual ( ( decimal ) 123.4, a2 ); Assert.AreEqual ( ( decimal ) 1234.5, a3 ); Assert.AreEqual ( ( decimal ) 1234.5, a4 ); Assert.AreEqual ( ( decimal ) 123, a5 ); Assert.AreEqual ( ( decimal ) 1234567.89, a6 ); Assert.AreEqual ( ( decimal ) 1234567.89, a7 ); } ///  /// ///  [TestMethod] public void Swap_Char_Test ( ) { string v6 = "1,234,567.89"; string v7 = "1.234.567,89"; string a1 = v6.SwapChar ( ',', '.' ); string a2 = v7.SwapChar ( ',', '.' ); Assert.AreEqual ( "1.234.567,89", a1 ); Assert.AreEqual ( "1,234,567.89", a2 ); } } 

很好,仍然不是100%正确。 当你使用案例1:你自动地假设,’,’代表十进制数字。 你应该至少检查它是否发生过多次,因此在这种情况下它会成为一个分组符号

  case 1: var firstPunctuation = linq.ElementAt(0); var firstPunctuationOccurence = value.Where(x => x == firstPunctuation).Count(); if (firstPunctuationOccurence == 1) { // we assume it's a decimal separator (and not a group separator) value = value.Replace(firstPunctuation.ToString(), format.NumberDecimalSeparator); } else { // multiple occurence means that symbol is a group separator value = value.Replace(firstPunctuation.ToString(), format.NumberGroupSeparator); } break;