【问题标题】:C# Double - ToString() formatting with two decimal places but no roundingC# Double - ToString() 格式有两位小数但没有四舍五入
【发布时间】:2011-01-28 01:52:38
【问题描述】:

如何在 C# 中将 Double 格式化为 String 以便只有两位小数?

如果我使用String.Format("{0:0.00}%", myDoubleValue),则数字会被四舍五入,我想要一个简单的截断而不进行任何四舍五入。我还希望转换为String 具有文化敏感性。

【问题讨论】:

  • “文化敏感”是什么意思?这是否意味着格式化的结果必须根据程序员提供的文化价值而有所不同?还是您想使用当前线程的默认文化?

标签: c# string double


【解决方案1】:

C# 函数,由 Kyle Rozendo 表示:

string DecimalPlaceNoRounding(double d, int decimalPlaces = 2)
{
    double factor = Math.Pow(10, decimalPlaces);
    d = d * factor;
    d = Math.Truncate(d);
    d = d / factor;
    return string.Format("{0:N" + Math.Abs(decimalPlaces) + "}", d);
}

【讨论】:

    【解决方案2】:

    我在使用 Xamarin Forms 时遇到了这个问题,并通过以下方式解决了它:

    percent.ToString("0.##"+"%")
    

    【讨论】:

      【解决方案3】:

      还要注意您系统的CultureInformation。这是我的解决方案,没有四舍五入。

      在本例中,您只需将变量 MyValue 定义为 double。 结果,您在字符串变量 NewValue 中获得格式化值。

      注意 - 还要设置 C# using 语句:

      using System.Globalization;  
      
      string MyFormat = "0";
      if (MyValue.ToString (CultureInfo.InvariantCulture).Contains (CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator))
         {
            MyFormat += ".00";
         }
      
      string NewValue = MyValue.ToString(MyFormat);
      

      【讨论】:

        【解决方案4】:

        解决方案:

        var d = 0.123345678; 
        var stringD = d.ToString(); 
        int indexOfP = stringD.IndexOf("."); 
        var result = stringD.Remove((indexOfP+1)+2);
        

        (indexOfP+1)+2(这个数字取决于你想要多少个数字 保存。我给它两个,因为问题所有者想要。)

        【讨论】:

          【解决方案5】:

          感谢.##,以下四舍五入数字,但仅显示最多 2 个小数位(删除任何尾随零)。

          decimal d0 = 24.154m;
          decimal d1 = 24.155m;
          decimal d2 = 24.1m;
          decimal d3 = 24.0m;
          
          d0.ToString("0.##");   //24.15
          d1.ToString("0.##");   //24.16 (rounded up)
          d2.ToString("0.##");   //24.1  
          d3.ToString("0.##");   //24
          

          http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/

          【讨论】:

          • 这不起作用。用 0.2415999 试试。此解决方案是四舍五入,而不是截断。
          • 哇,这么多赞成票,但它正在使用四舍五入。可能有必要指出,舍入是朝着要求的最接近的小数位前进,而截断是在要求的最接近的小数位之后截断。
          • @mysticcoder 我想我的回答得到了很多赞成,因为他们在谷歌搜索中以与我相同的方式来到 ops 问题,希望删除尾随零,而不是寻找四舍五入的愿望操作问题。我想我应该删除我的答案...
          • @BrianOgden - 不,请不要删除。我来到这里寻找你的答案。 +1
          【解决方案6】:

          对于价值,显示货币,您可以使用"C"

          double cost = 1.99;
          m_CostText.text = cost.ToString("C"); /*C: format as currentcy */
          

          输出:$1.99

          【讨论】:

            【解决方案7】:

            添加一个额外的小数如何舍入然后丢弃:

            var d = 0.241534545765;
            var result1 = d.ToString("0.###%");
            
            var result2 = result1.Remove(result1.Length - 1);
            

            【讨论】:

            • 有趣的是,一个无效的答案有 60 个投票(截至今天),而这个非常简单且防弹的解决方案只有一个......
            • 如果四舍五入影响截止值以上一位以上的数字,这将不起作用。例如 0.199999 将在此代码中以 0.20 结束,而不是 0.19。
            【解决方案8】:

            以下只能用于显示使用String ..的属性..

            double value = 123.456789;
            String.Format("{0:0.00}", value);
            

            【讨论】:

            • 这将给出“123.46”。该问题特别要求不四舍五入。
            【解决方案9】:

            最简单的方法,使用数字格式字符串:

            double total = "43.257"
            MessageBox.Show(total.ToString("F"));
            

            【讨论】:

            【解决方案10】:

            我知道这是一个旧线程,但我不得不这样做。虽然这里的其他方法有效,但我想要一种简单的方法来影响对string.format 的大量调用。因此,将Math.Truncate 添加到所有调用中并不是一个好的选择。此外,由于某些格式存储在数据库中,这使情况变得更糟。

            因此,我制作了一个自定义格式提供程序,它允许我在格式化字符串中添加截断,例如:

            string.format(new FormatProvider(), "{0:T}", 1.1299); // 1.12
            string.format(new FormatProvider(), "{0:T(3)", 1.12399); // 1.123
            string.format(new FormatProvider(), "{0:T(1)0,000.0", 1000.9999); // 1,000.9
            

            实现非常简单,很容易扩展到其他需求。

            public class FormatProvider : IFormatProvider, ICustomFormatter
            {
                public object GetFormat(Type formatType)
                {
                    if (formatType == typeof (ICustomFormatter))
                    {
                        return this;
                    }
                    return null;
                }
            
                public string Format(string format, object arg, IFormatProvider formatProvider)
                {
                    if (arg == null || arg.GetType() != typeof (double))
                    {
                        try
                        {
                            return HandleOtherFormats(format, arg);
                        }
                        catch (FormatException e)
                        {
                            throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
                        }
                    }
            
                    if (format.StartsWith("T"))
                    {
                        int dp = 2;
                        int idx = 1;
                        if (format.Length > 1)
                        {
                            if (format[1] == '(')
                            {
                                int closeIdx = format.IndexOf(')');
                                if (closeIdx > 0)
                                {
                                    if (int.TryParse(format.Substring(2, closeIdx - 2), out dp))
                                    {
                                        idx = closeIdx + 1;
                                    }
                                }
                                else
                                {
                                    throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
                                }
                            }
                        }
                        double mult = Math.Pow(10, dp);
                        arg = Math.Truncate((double)arg * mult) / mult;
                        format = format.Substring(idx);
                    }
            
                    try
                    {
                        return HandleOtherFormats(format, arg);
                    }
                    catch (FormatException e)
                    {
                        throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
                    }
                }
            
                private string HandleOtherFormats(string format, object arg)
                {
                    if (arg is IFormattable)
                    {
                        return ((IFormattable) arg).ToString(format, CultureInfo.CurrentCulture);
                    }
                    return arg != null ? arg.ToString() : String.Empty;
                }
            }
            

            【讨论】:

              【解决方案11】:

              我使用price.ToString("0.00") 获得领先的 0

              【讨论】:

                【解决方案12】:

                这对我有用

                string prouctPrice = Convert.ToDecimal(String.Format("{0:0.00}", Convert.ToDecimal(yourString))).ToString();
                

                【讨论】:

                  【解决方案13】:

                  我使用以下:

                  double x = Math.Truncate(myDoubleValue * 100) / 100;
                  

                  例如:

                  如果号码是 50.947563 并且您使用以下内容,则会发生以下情况:

                  - Math.Truncate(50.947563 * 100) / 100;
                  - Math.Truncate(5094.7563) / 100;
                  - 5094 / 100
                  - 50.94
                  

                  你的答案被截断了,现在要格式化字符串,只需执行以下操作:

                  string s = string.Format("{0:N2}%", x); // No fear of rounding and takes the default number format
                  

                  【讨论】:

                  • -1 您可以在格式化字符串的同一string.Format 步骤中进行文化敏感格式化。请参阅下面的答案。
                  • 太好了。我希望我的评论现在看起来不那么愚蠢。 :-) 我会改变我的反对票。
                  • 对我来说确实如此,因为字符串格式的解决方案非常简单,截断更棘手。
                  • 很遗憾,当数字小于 1 时,您的解决方案不起作用,以说明:0.97,这种情况有什么解决方法吗?
                  • @Jonny 不起作用,因为它会四舍五入 - OP 希望它截断(而不是四舍五入)。差别很微妙。
                  【解决方案14】:

                  您也可以编写自己的IFormatProvider,但我想最终您必须想办法进行实际截断。

                  .NET Framework 还支持自定义格式。这通常涉及创建实现 IFormatProvider 和 ICustomFormatter 的格式化类。 (msdn)

                  至少它可以很容易地重复使用。

                  有一篇文章介绍了如何实现自己的IFormatProvider/ICustomFormatterhere at CodeProject。在这种情况下,“扩展”现有的数字格式可能是最好的选择。看起来不太难。

                  【讨论】:

                    【解决方案15】:

                    我建议你先截断,再格式化:

                    double a = 123.4567;
                    double aTruncated = Math.Truncate(a * 100) / 100;
                    CultureInfo ci = new CultureInfo("de-DE");
                    string s = string.Format(ci, "{0:0.00}%", aTruncated);
                    

                    使用常数 100 截断 2 位数字;使用 1 后跟与您想要的小数点后数字一样多的零。使用你需要的区域性名称来调整格式化结果。

                    【讨论】:

                    • 我认为应该使用静态属性Culture.InvariantCulture而不是new CultureInfo("de-DE")
                    猜你喜欢
                    • 1970-01-01
                    • 2015-07-31
                    • 1970-01-01
                    • 2011-03-09
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-01-02
                    • 1970-01-01
                    相关资源
                    最近更新 更多