Using String Format to show decimal up to 2 places

2019-01-01 05:09发布

问题:

I have got a price field to display which sometimes can be either 100 or 100.99 or 100.9, What I want is to display the price in 2 decimal places only if the decimals are entered for that price , for instance if its 100 so it should only show 100 not 100.00 and if the price is 100.2 it should display 100.20 similarly for 100.22 should be same . I googled and came across some examples but they didn\'t match exactly what i wanted :

// 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:

An inelegant way would be:

var my = DoFormat(123.0);

With DoFormat being something like:

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

Not elegant but working for me in similar situations in some projects.



回答2:

Sorry for reactivating this question, but I didn\'t find the right answer here.

In formatting numbers you can use 0 as a mandatory place and # as an optional place.

So:

// 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\"

You can also combine 0 with #.

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\"

For this formating method is always used CurrentCulture. For some Cultures . will be changed to ,.



回答3:

This is a common formatting floating number use case.

Unfortunately, all of the built-in one-letter format strings (eg. F, G, N) won\'t achieve this directly.
For example, num.ToString(\"F2\") will always show 2 decimal places like 123.40.

You\'ll have to use 0.## pattern even it looks a little verbose.

A complete code example:

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


回答4:

Old question but I wanted to add the simplest option in my opinion.

Without thousands separators:

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

With thousands separators:

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

The same but with 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

If you need it in many places, I would use this logic in an extension method:

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


回答5:

try

double myPrice = 123.0;

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


回答6:

I don\'t know of anyway to put a condition in the format specifier, but you can write your own formatter:

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


回答7:

Simple one line code :

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


回答8:

Here is an alternative to Uwe Keim\'s method, which would still maintain the same method call:

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

With MyCustomFormat being something like:

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


回答9:

I am afraid there is no built-in format that will do this. You will have to use a different format depending on whether the value is a whole number or not. Or always format to 2 decimal places, and manipulate the string afterwards to remove any trailing \".00\".



回答10:

If none of the other answers work for you, it may be because you are binding the ContentProperty of a control in the OnLoad function, which means this won\'t work:

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

The solution is simple: there is a ContentStringFormat property in the xaml. So when you create the label do this:

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

Or

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


回答11:

something like this will work too:

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


回答12:

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



回答13:

If your program needs to run quickly, call value.ToString(formatString) for ~35% faster string formatting performance relative to $\"{value:formatString}\" and string.Format(formatString, value).

Data

\"C#

Code

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

Code Output

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

References

Custom Numeric Format Strings [docs.microsoft.com]

Qt Charts BarChart Example [doc.qt.io]



回答14:

To make the code more clear that Kahia wrote in (it is clear but gets tricky when you want to add more text to it)...try this simple solution.

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

I had to add the extra cast (decimal) to have Math.Round compare the two decimal variables.



回答15:

This worked for me!

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