【问题标题】:Using String Format to show decimal up to 2 places or simple integer使用字符串格式显示最多 2 位的小数或简单整数
【发布时间】:2011-10-20 13:10:16
【问题描述】:

我有一个要显示的价格字段,有时可以是 100 或 100.99 或 100.9,我想要的是仅在为该价格输入小数时以 2 位小数显示价格,例如,如果它是 100,那么它应该只显示 100 而不是 100.00,如果价格是 100.2,它应该显示 100.20,同样 100.22 应该是相同的。 我用谷歌搜索并遇到了一些示例,但它们与我想要的不完全匹配:

// just two decimal places
String.Format("{0:0.00}", 123.4567);      // "123.46"
String.Format("{0:0.00}", 123.4);         // "123.40"
String.Format("{0:0.00}", 123.0);         // "123.00"

【问题讨论】:

  • RE:“我想要的是仅在为该价格输入小数时以 2 位小数显示价格”——因此,如果用户键入“100.00”,您希望显示“100.00” ,但如果他们键入“100”,您只想显示“100”? -- 数字类型只跟踪数字的值 -- 而不是用户输入了哪些无关紧要的数字,哪些没有 -- 为此您需要使用字符串。
  • @BinaryWorrier 我认为这个问题可能是重复的,但它有更好和更完整的答案。 IMO 应将另一个标记为该副本的副本。
  • 只需添加 .Replace(".00","")
  • 您只需要value.ToString("0.##");

标签: c# regex string-formatting number-formatting


【解决方案1】:

很抱歉重新激活这个问题,但我在这里没有找到正确的答案。

在格式化数字时,您可以使用0 作为必填位置,# 作为可选位置。

所以:

// just two decimal places
String.Format("{0:0.##}", 123.4567);      // "123.46"
String.Format("{0:0.##}", 123.4);         // "123.4"
String.Format("{0:0.##}", 123.0);         // "123"

您还可以将0# 结合使用。

String.Format("{0:0.0#}", 123.4567)       // "123.46"
String.Format("{0:0.0#}", 123.4)          // "123.4"
String.Format("{0:0.0#}", 123.0)          // "123.0"

对于这种格式化方法,总是使用CurrentCulture。对于某些文化,. 将更改为 ,

回答原问题:

最简单的解决方案来自@Andrew (here)。所以我个人会使用这样的东西:

var number = 123.46;
String.Format(number % 1 == 0 ? "{0:0}" : "{0:0.00}", number)

【讨论】:

  • 起初,我认为这应该是答案,直到我多次重新阅读原始问题。 OP 并不完全清楚他到底想要什么,但如果有人输入分数,他似乎总是想要 2 位小数。因此,如果有人输入 1.1,那么他会想要 1.10;这段代码不会那样做。
  • 糟糕,我又读了一遍,你是对的。所以,这不是正确的答案,但至少有人会觉得这很有用。
  • OP 需要的可以用这个来实现:stackoverflow.com/a/33180829/2321042
  • 我刚刚发现它很有用,并且(在某种程度上)与 GridView 中的 BoundField 使用 SqlDouble 和无格式指令所做的相匹配。您必须指出您将显示的最大#。 (与 BoundField 相比,很高兴显示尽可能多或尽可能少)
  • 是的,这很有用,但是如果存在小数点,如何只显示两个小数点?即如果它是一个整数,那么不显示小数?
【解决方案2】:

一种不优雅的方式是:

var my = DoFormat(123.0);

DoFormat 类似于:

public static string DoFormat( double myNumber )
{
    var s = string.Format("{0:0.00}", myNumber);

    if ( s.EndsWith("00") )
    {
        return ((int)myNumber).ToString();
    }
    else
    {
        return s;
    }
}

不优雅,但在某些项目的类似情况下为我工作。

【讨论】:

  • 这并不是真正被问到的问题——但如果是这样的话——为什么不直接使用 string.Format("{0:0.00}").Replace(".00", "")?
  • @BrainSlugs83:取决于当前线程的CurrentCulture,小数点分隔符可能不是.。除非CultureInfo.InvariantCulturestring.Format 一起使用,否则您必须检查CultureInfo.NumberFormat.NumberDecimalSeparator 的值,这将是一个真正的PITA。 :)
  • @Uwe Keim 如果我有 60000 int 并且我希望它是 60.000 怎么办?
  • 这个答案是一个“重新发明方轮”的案例。不考虑文化或 .NET 已处理这一事实。
【解决方案3】:

这是一个常见的格式化浮点数用例。

很遗憾,所有内置的单字母格式字符串(例如 F、G、N)都不能直接实现这一点。
例如,num.ToString("F2") 将始终显示 2 位小数,如 123.40

你必须使用 0.## 模式,即使它看起来有点冗长。

完整的代码示例:

double a = 123.4567;
double b = 123.40;
double c = 123.00;

string sa = a.ToString("0.##"); // 123.46
string sb = b.ToString("0.##"); // 123.4
string sc = c.ToString("0.##"); // 123

【讨论】:

  • 但他想要 123.40,而不是 123.4。
  • 不是解决这个问题,而是解决我的问题。我对此表示赞同,以便让其他人看到。
【解决方案4】:

老问题,但我想添加我认为最简单的选项。

没有千位分隔符:

value.ToString(value % 1 == 0 ? "F0" : "F2")

使用千位分隔符:

value.ToString(value % 1 == 0 ? "N0" : "N2")

相同,但使用 String.Format

String.Format(value % 1 == 0 ? "{0:F0}" : "{0:F2}", value) // Without thousands separators
String.Format(value % 1 == 0 ? "{0:N0}" : "{0:N2}", value) // With thousands separators

如果您在很多地方需要它,我会在扩展方法中使用这个逻辑:

public static string ToCoolString(this decimal value)
{
    return value.ToString(value % 1 == 0 ? "N0" : "N2"); // Or F0/F2 ;)
}

【讨论】:

    【解决方案5】:

    试试

    double myPrice = 123.0;
    
    String.Format(((Math.Round(myPrice) == myPrice) ? "{0:0}" : "{0:0.00}"), myPrice);
    

    【讨论】:

    • string.Format((number % 1) == 0 ? "{0:0}" : "{0:0.00}", number);
    【解决方案6】:

    如果您的程序需要快速运行,请调用 value.ToString(formatString) 相对于 $"{value:formatString}" 和 string.Format(formatString, value) 将字符串格式化性能提高约 35%。

    数据

    代码

    using System;
    using System.Diagnostics;
    
    public static class StringFormattingPerformance
    {
       public static void Main()
       {
          Console.WriteLine("C# String Formatting Performance");
          Console.WriteLine("Milliseconds Per 1 Million Iterations - Best Of 5");
          long stringInterpolationBestOf5 = Measure1MillionIterationsBestOf5(
              (double randomDouble) =>
              {
                 return $"{randomDouble:0.##}";
              });
          long stringDotFormatBestOf5 = Measure1MillionIterationsBestOf5(
              (double randomDouble) =>
              {
                 return string.Format("{0:0.##}", randomDouble);
              });
          long valueDotToStringBestOf5 = Measure1MillionIterationsBestOf5(
              (double randomDouble) =>
              {
                 return randomDouble.ToString("0.##");
              });
          Console.WriteLine(
    $@"            $""{{value:formatString}}"": {stringInterpolationBestOf5} ms
     string.Format(formatString, value): {stringDotFormatBestOf5} ms
           value.ToString(formatString): {valueDotToStringBestOf5} ms");
       }
    
       private static long Measure1MillionIterationsBestOf5(
           Func<double, string> formatDoubleUpToTwoDecimalPlaces)
       {
          long elapsedMillisecondsBestOf5 = long.MaxValue;
          for (int perfRunIndex = 0; perfRunIndex < 5; ++perfRunIndex)
          {
             var random = new Random();
             var stopwatch = Stopwatch.StartNew();
             for (int i = 0; i < 1000000; ++i)
             {
                double randomDouble = random.NextDouble();
                formatDoubleUpToTwoDecimalPlaces(randomDouble);
             }
             stopwatch.Stop();
             elapsedMillisecondsBestOf5 = Math.Min(
                elapsedMillisecondsBestOf5, stopwatch.ElapsedMilliseconds);
          }
          return elapsedMillisecondsBestOf5;
       }
    }
    

    代码输出

    C# String Formatting Performance
    Milliseconds Per 1 Million Iterations - Best Of 5
                $"{value:formatString}": 419 ms
     string.Format(formatString, value): 419 ms
           value.ToString(formatString): 264 ms
    

    参考

    Custom Numeric Format Strings [docs.microsoft.com]

    Qt Charts BarChart Example [doc.qt.io]

    【讨论】:

    • 很高兴知道它可以在 $string 符号中完成。如果它没有在一个紧密的循环中使用,那么就不用担心性能受到影响。
    • 这主要是由于拳击和其他额外的分配。有关详细信息,请参阅this answer
    【解决方案7】:

    无论如何我都不知道要在格式说明符中添加条件,但是您可以编写自己的格式化程序:

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                   // all of these don't work
                Console.WriteLine("{0:C}", 10);
                Console.WriteLine("{0:00.0}", 10);
                Console.WriteLine("{0:0}", 10);
                Console.WriteLine("{0:0.00}", 10);
                Console.WriteLine("{0:0}", 10.0);
                Console.WriteLine("{0:0}", 10.1);
                Console.WriteLine("{0:0.00}", 10.1);
    
              // works
                Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9));
                Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9.1));
                Console.ReadKey();
            }
        }
    
        class MyFormatter : IFormatProvider, ICustomFormatter
        {
            public string Format(string format, object arg, IFormatProvider formatProvider)
            {
                switch (format.ToUpper())
                {
                    case "CUSTOM":
                        if (arg is short || arg is int || arg is long)
                            return arg.ToString();
                        if (arg is Single || arg is Double)
                            return String.Format("{0:0.00}",arg);
                        break;
                    // Handle other
                    default:
                        try
                        {
                            return HandleOtherFormats(format, arg);
                        }
                        catch (FormatException e)
                        {
                            throw new FormatException(String.Format("The format of '{0}' is invalid.", format), e);
                        }
                }
                return arg.ToString(); // only as a last resort
            }
    
            private string HandleOtherFormats(string format, object arg)
            {
                if (arg is IFormattable)
                    return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
                if (arg != null)
                    return arg.ToString();
                return String.Empty;
            }
    
            public object GetFormat(Type formatType)
            {
                if (formatType == typeof(ICustomFormatter))
                    return this;
                return null;
            }
        }
    }
    

    【讨论】:

      【解决方案8】:

      这里是 Uwe Keim 方法的替代方法,它仍将保持相同的方法调用:

      var example1 = MyCustomFormat(123.1);  // Output: 123.10
      var example2 = MyCustomFormat(123.95); // Output: 123.95
      var example3 = MyCustomFormat(123);    // Output: 123
      

      MyCustomFormat 类似于:

      public static string MyCustomFormat( double myNumber )
      {
          var str (string.Format("{0:0.00}", myNumber))
          return (str.EndsWith(".00") ? str.Substring(0, strLastIndexOf(".00")) : str;
      }
      

      【讨论】:

      • 这对我不起作用,因为似乎 TrimEnd 需要一个像 {',', '.', ' '} 这样的字符数组,而不是像 ".00" 这样的字符串 - 请参阅 @987654321 @
      • 你是对的 - 不知道我是怎么错过的。我已更新以正常工作。
      • 根据当前线程的CurrentCulture,小数点分隔符可能不是.。除非CultureInfo.InvariantCulturestring.Format 一起使用,否则您必须检查CultureInfo.NumberFormat.NumberDecimalSeparator 的值,这是相当不雅的。
      【解决方案9】:

      简单的一行代码:

      public static string DoFormat(double myNumber)
      {
          return string.Format("{0:0.00}", myNumber).Replace(".00","");
      }
      

      【讨论】:

      • 这个问题是如果它在小数点分隔符是逗号的地方运行。检查 this answer 的 cmets。
      【解决方案10】:

      恐怕没有内置格式可以做到这一点。您必须使用不同的格式,具体取决于该值是否为整数。或者始终格式化为 2 位小数,然后操作字符串以删除任何尾随的“.00”。

      【讨论】:

        【解决方案11】:

        试试:

        String.Format("{0:0.00}", Convert.ToDecimal(totalPrice));
        

        【讨论】:

          【解决方案12】:

          如果其他答案都不适合您,可能是因为您在OnLoad 函数中绑定了控件的ContentProperty,这意味着这不起作用:

          private void UserControl_Load(object sender, RoutedEventArgs e)
          {
            Bind.SetBindingElement(labelName, String.Format("{0:0.00}", PropertyName), Label.ContentProperty) 
          }
          

          解决方案很简单:xaml 中有一个ContentStringFormat 属性。因此,当您创建标签时,请执行以下操作:

          //if you want the decimal places definite
          <Label Content="0" Name="labelName" ContentStringFormat="0.00"/>
          

          或者

          //if you want the decimal places to be optional
          <Label Content="0" Name="labelName" ContentStringFormat="0.##"/>
          

          【讨论】:

            【解决方案13】:

            类似的方法也可以:

            String.Format("{0:P}", decimal.Parse(Resellers.Fee)).Replace(".00", "")
            

            【讨论】:

            • 那给出一个百分比?
            【解决方案14】:

            在处理来自 (T-)SQL 数据库的小数时,您希望能够转换具有 x 个小数位的可空和不可空小数,并能够根据您的表定义轻松查看代码 - 当然还有,向用户显示正确的小数位数。

            不幸的是,Entity Framework 不会自动将诸如 SQL decimal(18,2) 之类的内容转换为具有相同小数位数的 .NET 等效项(因为只有全精度的小数可用)。您必须手动截断小数位。

            所以,我是这样做的:

            public static class Extensions
            {
                public static string ToStringDecimal(this decimal d, byte decimals)
                {
                    var fmt = (decimals>0) ? "0." + new string('0', decimals) : "0";
                    return d.ToString(fmt);
                }
            
                public static string ToStringDecimal(this decimal? d, byte decimals)
                {
                    if (!d.HasValue) return "";
                    return ToStringDecimal(d.Value, decimals);
                }
            }
            

            示例用法:

            void Main()
            {
                decimal d = (decimal)1.2345;
                decimal? d2 = null; 
            
                Console.WriteLine(d.ToStringDecinal(2)); // prints: "1.23" (2 decimal places)
                Console.WriteLine(d.ToStringDecinal(0)); // prints: "1" (show integer number)
                Console.WriteLine(d2.ToStringDecimal(2)); // prints: "" (show null as empty string)
            }
            

            【讨论】:

              【解决方案15】:

              为了使 Kahia 编写的代码更加清晰(虽然清晰,但是当您想向其中添加更多文本时会变得很棘手)...试试这个简单的解决方案。

              if (Math.Round((decimal)user.CurrentPoints) == user.CurrentPoints)
                   ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0}",user.CurrentPoints);
              else
                   ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0.0}",user.CurrentPoints);
              

              我必须添加额外的强制转换(十进制)才能让 Math.Round 比较两个十进制变量。

              【讨论】:

                【解决方案16】:

                这对我有用!

                String amount= "123.0000";
                String.Format("{0:0.##}", amount);      // "123.00"
                

                【讨论】:

                • 那行不通。他希望 123.00 显示为“123”,而 123.50 显示为“123.50”。
                【解决方案17】:

                最近的一个项目有类似的要求。我写了这个十进制扩展方法, 它使用currency ("C") Format Specifier。除了去除零外,它还有十进制数字精度、货币符号、分隔符和文化选项。

                public static DecimalExtension{
                
                     public static string ToCurrency(this decimal val, 
                                                     int precision = 2, 
                                                     bool currencySymbol = false, 
                                                     bool separator = false, 
                                                     CultureInfo culture = null)
                      {     
                         if(culture == null) culture = new CultureInfo("en-US");
                                                                   
                         NumberFormatInfo nfi = culture.NumberFormat;
                         nfi.CurrencyDecimalDigits = precision;
                            
                         string zeros = new String('0', precision);       
                                    
                         //Remove zeros
                         var result = val.ToString("C",fi).Replace(nfi.CurrencyDecimalSeparator + zeros,"");
                                     
                         if(!separator) result = result.Replace(nfi.CurrencyGroupSeparator,"");
                                    
                         return currencySymbol? result: result.Replace(nfi.CurrencySymbol,"");      
                        }   
                }
                

                例子:

                decimal Total = 123.00M;
                Console.WriteLine(Total.ToCurrency());  
                //output: 123
                
                decimal Total = 1123.12M;
                Console.WriteLine(Total.ToCurrency()); 
                //Output:  1123.12
                
                Console.WriteLine(Total.ToCurrency(4));
                //Output:  1123.1200
                
                Console.WriteLine(Total.ToCurrency(2,true,true));
                //output:  $1,123.12
                 
                CultureInfo culture = new CultureInfo("pt-BR")  //Brazil
                Console.WriteLine(Total.ToCurrency(2,true,true, culture));
                //output:  R$ 1.123,12
                

                【讨论】:

                  【解决方案18】:

                  试试这个

                  string Output = String.Format("{0:0.00}", Decimal.Parse(InputStringValue));
                  

                  【讨论】:

                    【解决方案19】:

                    要获得一位、两位、三位或四位小数,您可以尝试以下格式来代替 123,您可以放置​​自己需要的输出

                    Input                                         Output
                    
                    String.Format("{0:0.0}", "123.0")               123.0    // For 1 decimal place
                    String.Format("{0:0.00}", "123.00")           123.00   // For 2 decimal place
                    String.Format("{0:0.000}", "123.000")         123.000  // For 3 decimal place
                    String.Format("{0:0.0000}", "123.0000")       123.0000 // For 4 decimal place
                    

                    【讨论】:

                    • 请在您的回答中添加一些解释。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-02-12
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-09-02
                    • 1970-01-01
                    相关资源
                    最近更新 更多