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开发者_Python百科.0); // "123.00"
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 ,
.
Answer to original question:
The simpliest solution comes from @Andrew (here). So I personally would use something like this:
var number = 123.46;
String.Format(number % 1 == 0 ? "{0:0}" : "{0:0.00}", number)
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.
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
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 ;)
}
try
double myPrice = 123.0;
String.Format(((Math.Round(myPrice) == myPrice) ? "{0:0}" : "{0:0.00}"), myPrice);
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
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 [learn.microsoft.com]
Qt Charts BarChart Example [doc.qt.io]
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;
}
}
}
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;
}
Simple one line code :
public static string DoFormat(double myNumber)
{
return string.Format("{0:0.00}", myNumber).Replace(".00","");
}
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".
Try:
String.Format("{0:0.00}", Convert.ToDecimal(totalPrice));
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.##"/>
something like this will work too:
String.Format("{0:P}", decimal.Parse(Resellers.Fee)).Replace(".00", "")
When dealing with decimals coming from a (T-)SQL database, you want to be able to convert nullable and non-nullable decimals with x decimal places and be able to review the code easily against your table definitions - and of course, display the right number of decimals to the user.
Unfortunately, the Entity Framework doesn't automatically convert something like a SQL decimal(18,2)
into a .NET equivalent with the same number of decimal places (since there is only decimal with full precision available). You have to truncate the decimal places manually.
So, I did it this way:
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);
}
}
Example Usage:
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)
}
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.
Try this:
var number = 123.4567;
var str = number.ToString("N2");
A recent project has a similar requirement. I wrote this decimal extension method, which uses the currency ("C") Format Specifier. In addition to removing zeros, it also has options for decimal digits precision, currency symbol, separator and culture.
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,"");
}
}
Examples:
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
Try This
string Output = String.Format("{0:0.00}", Decimal.Parse(InputStringValue));
精彩评论