代码之家  ›  专栏  ›  技术社区  ›  Andrew Florko

将字符串转换为十进制分隔符“.”和“,”的最佳方法是什么?

  •  18
  • Andrew Florko  · 技术社区  · 14 年前

    应用程序处理表示来自不同区域性的小数的字符串。

    我玩过 Decimal.TryParse 标记组合,但无法达到我想要的结果。”1,1“终究变成了“11”或“0”。

    NumberFormat.NumberDecimalSeparator ?

    你如何处理这种情况?

    提前谢谢你!

    7 回复  |  直到 14 年前
        1
  •  6
  •   Otiel user577803    11 年前

    你有以下可能:

      1. 使用安装了计算机的当前区域性设置
      2. 您让用户决定在程序中设置其区域性->用户设置
    1. 你不懂文化
      1. 你必须决定:你必须定义和记录你的决定
        2
  •  34
  •   Jeff Mercado    14 年前

    您可以创建一个临时 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
    
        3
  •  11
  •   NoWar    10 年前

    所以如果你不知道目标系统的文化,你也不知道你会得到什么样的价值,比如12.33或者12,33,你可以这样做

    string amount = "12.33";
    // or i.e. 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); 
    
        4
  •  4
  •   Noon Silk    14 年前

    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);
    
        5
  •  3
  •   Andy    14 年前

    下面是我的实现,有什么好主意吗?

    /// <summary>
    /// 
    /// </summary>
    public static class NumberExtensions
    {
        /// <summary>
        /// Convert string value to decimal ignore the culture.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>Decimal value.</returns>
        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;
        }
        /// <summary>
        /// Swaps the char.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="from">From.</param>
        /// <param name="to">To.</param>
        /// <returns></returns>
        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
    {
    
        /// <summary>
        /// 
        /// </summary>
        [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 );
        }
        /// <summary>
        /// 
        /// </summary>
        [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 );
        }
    }
    
        6
  •  2
  •   ajoka    13 年前

    很好,仍然不是100%正确。

                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;
    
        7
  •  0
  •   KalifUmestoKalifa    5 年前

    使用胰蛋白酶两次,两种风格代表两种可能性
    如果只有一个返回值,则使用该值 如果两者都返回一个值,则使用绝对值中较小的值。

    如果使用错误的样式,对于同时使用分组和小数分隔符的数字,TryParse将返回0,但是如果字符串中没有分组分隔符(例如,数字小于1000),则在这两种情况下都将返回值,但“错误”的数字将更大(同样是绝对值)