使用字符串格式最多显示两位小数或简单整数


291

我有一个要显示的价格字段,有时可以是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"


1
RE:“我想要的是,仅当输入该价格的小数位数时,才将价格显示在小数点后两位” –因此,如果用户键入“ 100.00”,则要显示“ 100.00”,但是如果他们键入“ 100”您只想显示“ 100”?-数字类型仅跟踪数字的值-不是用户输入的那些无关紧要的数字,不是用户输入的无关紧要的数字-为此,您将需要使用字符串。
BrainSlugs83

2
@BinaryWorrier我认为这个问题可能是重复的,但是它有更好,更完整的答案。国际海事组织,另一项应标记为该项的副本。
瑞安·盖茨

只需添加.Replace(“。00”,“”)
Dave Sumter

Answers:


155

一个优雅的方法是:

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;
    }
}

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


6
这不是真正要问的问题-曾经是-为什么不只使用string.Format(“ {0:0.00}”)。Replace(“。00”,“”)?
BrainSlugs83

18
@ BrainSlugs83:根据当前线程的不同CurrentCulture,小数点分隔符可能不是.。除非CultureInfo.InvariantCulture与一起使用string.Format,否则您必须检查的值CultureInfo.NumberFormat.NumberDecimalSeparator,这将是真实的PITA。:)
Groo

@Uwe Keim如果我有60000智力并且我想要它会60.000怎样?
Prashant Pimpale

这个答案是“重新发明方形齿轮”的情况。不考虑文化或.NET已经处理过这一事实。
bytedev

522

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

在格式化数字时,您可以将其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(在此)。所以我个人会使用这样的东西:

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

20
起初,我认为这应该是答案,直到我多次重新阅读原始问题。OP并不确定他到底想要什么,但是如果有人输入分数,他似乎总是想要小数点后两位。因此,如果有人输入1.1,那么他想要1.10。该代码不会那样做。
道格S

40
糟糕,我又读了一次,您是对的。因此,这不是正确的答案,但至少有人可能会觉得有用。
2014年

所需的OP可以通过以下方法实现:stackoverflow.com/a/33180829/2321042
Andrew

我只是发现它很有用,并且(某种程度上)将GridView中的BoundField与SqlDouble和无格式指令进行匹配。您必须指出要显示的最大编号。(与BoundField相对,很高兴显示
任意多或少的内容

是的,这很有用,但是如果存在小数,如何只显示两个小数呢?即,如果其为整数,则不显示小数?
Nigel Fds

64

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

不幸的是,所有内置的单字母格式字符串(例如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

7
但是他想要123.40,而不是123.4。
Andrew

8
不是解决这个问题,而是解决我的问题。我对此表示赞同,以供其他所有人看到。
Emad

46

旧问题,但我想添加最简单的选择。

没有数千个分隔符:

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 ;)
}

28

尝试

double myPrice = 123.0;

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

5
string.Format((数字%1)== 0?“ {0:0}”:“ {0:0.00}”,数字);
帕特里克(Patrick)

8

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

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;
        }
    }
}

6

这是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”这样的字符串-请参阅msdn.microsoft.com/zh-cn/ library / system.string.trimend.aspx
user1069816 2013年

您是对的-不确定我怎么想的。我已更新为可以正常工作。
史蒂夫(Steve)

5
根据当前线程的不同CurrentCulture,小数点分隔符可能不是.。除非CultureInfo.InvariantCulture与一起使用string.Format,否则您必须检查的值CultureInfo.NumberFormat.NumberDecimalSeparator,这非常小。
Groo 2014年

6

简单的一行代码:

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

问题是如果它在小数点分隔符是逗号的地方运行。查看此答案的评论。
安德鲁

6

如果您的程序需要快速运行,则调用value.ToString(formatString)可使字符串格式化性能比$“ {value:formatString}”和string.Format(formatString,value)快约35%。

数据

C#字符串格式化性能-VS2017 15.4.5

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

参考文献

自定义数字格式字符串[docs.microsoft.com]

Qt图表BarChart示例[doc.qt.io]


5

恐怕没有内置格式可以做到这一点。您将必须使用不同的格式,具体取决于该值是否为整数。或始终将其格式设置为2个小数位,然后再处理该字符串以删除所有结尾的“ .00”。


4

如果没有其他答案对您有用,则可能是因为您ContentPropertyOnLoad函数中绑定了控件的,这意味着该方法不起作用:

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

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

//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.##"/>

3

这样的事情也将起作用:

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

那给出一个百分比?

3

尝试:

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

2

为了使代码更加清楚,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比较两个十进制变量。



1

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

不幸的是,实体框架不会自动将类似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)
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.