Best way to display decimal without trailing zeroes
Solution 1
Do you have a maximum number of decimal places you'll ever need to display? (Your examples have a max of 5).
If so, I would think that formatting with "0.#####" would do what you want.
static void Main(string[] args)
{
var dList = new decimal[] { 20, 20.00m, 20.5m, 20.5000m, 20.125m, 20.12500m, 0.000m };
foreach (var d in dList)
Console.WriteLine(d.ToString("0.#####"));
}
Solution 2
I just learned how to properly use the G
format specifier. See the MSDN Documentation. There is a note a little way down that states that trailing zeros will be preserved for decimal types when no precision is specified. Why they would do this I do not know, but specifying the maximum number of digits for our precision should fix that problem. So for formatting decimals, G29
is the best bet.
decimal test = 20.5000m;
test.ToString("G"); // outputs 20.5000 like the documentation says it should
test.ToString("G29"); // outputs 20.5 which is exactly what we want
Solution 3
This string format should make your day: "0.#############################". Keep in mind that decimals can have at most 29 significant digits though.
Examples:
? (1000000.00000000000050000000000m).ToString("0.#############################")
-> 1000000.0000000000005
? (1000000.00000000000050000000001m).ToString("0.#############################")
-> 1000000.0000000000005
? (1000000.0000000000005000000001m).ToString("0.#############################")
-> 1000000.0000000000005000000001
? (9223372036854775807.0000000001m).ToString("0.#############################")
-> 9223372036854775807
? (9223372036854775807.000000001m).ToString("0.#############################")
-> 9223372036854775807.000000001
Solution 4
This is yet another variation of what I saw above. In my case I need to preserve all significant digits to the right of the decimal point, meaning drop all zeros after the most significant digit. Just thought it would be nice to share. I cannot vouch for the efficiency of this though, but when try to achieve aesthetics, you are already pretty much damned to inefficiencies.
public static string ToTrimmedString(this decimal target)
{
string strValue = target.ToString(); //Get the stock string
//If there is a decimal point present
if (strValue.Contains("."))
{
//Remove all trailing zeros
strValue = strValue.TrimEnd('0');
//If all we are left with is a decimal point
if (strValue.EndsWith(".")) //then remove it
strValue = strValue.TrimEnd('.');
}
return strValue;
}
That's all, just wanted to throw in my two cents.
Solution 5
Another solution, based on dyslexicanaboko's answer, but independent of the current culture:
public static string ToTrimmedString(this decimal num)
{
string str = num.ToString();
string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
if (str.Contains(decimalSeparator))
{
str = str.TrimEnd('0');
if(str.EndsWith(decimalSeparator))
{
str = str.RemoveFromEnd(1);
}
}
return str;
}
public static string RemoveFromEnd(this string str, int characterCount)
{
return str.Remove(str.Length - characterCount, characterCount);
}
JC.
Updated on September 10, 2020Comments
-
JC. over 3 years
Is there a display formatter that will output decimals as these string representations in c# without doing any rounding?
// decimal -> string 20 -> 20 20.00 -> 20 20.5 -> 20.5 20.5000 -> 20.5 20.125 -> 20.125 20.12500 -> 20.125 0.000 -> 0
{0.#} will round, and using some Trim type function will not work with a bound numeric column in a grid.
-
Anthony Pegram almost 14 yearsAnd you can always throw an exorbitant* number of # symbols at the format. *not scientific
-
jgauffin almost 14 yearsgr8. Now you only have "0.0" left. Would procuce an empty string with your code.
-
TrueWill almost 14 years+1 - incidentally, you don't need the leading #. "0.#####" works identically. And either way, this does round away from zero (just FYI).
-
Ε Г И І И О over 12 yearsThen I would suggest calling .ToString().TrimEnd('0').TrimEnd('.'). Also instead of '.' its better to have CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator so that it works across cultures.
-
sehe about 12 yearsThis will lead to 0.00001 displayed as 1E-05 though
-
AaronLS over 11 years@TrueWill Actually it does make a difference. d==0.1m then "0.#" renders "0.1" and "#.#" renders ".1" without the leading 0. Neither is wrong or right, just depends on what you want.
-
Ethan Reesor over 9 years@Mervin, please change your answer to reflect ΕГИІИО's comment. Your code would format
50.0m
as5
, which is obviously an error. -
Vadim over 9 years"20.00 --> 2" I think it is not good behaviour. To fix it call TrimEnd two times: TrimEnd('0'); TrimEnd(',');
-
Sevin7 almost 8 yearsDO NOT USE the code written above. @VadymK is correct that its behavior is flawed. It will trim trailing zeros that are BEFORE the period if there is no period.
-
Eric Roller over 6 yearsThis is the most general answer to the problem. Not sure why this isn't the default "G" format for decimal. The trailing zeros add no information. Microsoft documentation has a weird caveat for decimal: docs.microsoft.com/en-us/dotnet/standard/base-types/… However, if the number is a Decimal and the precision specifier is omitted, fixed-point notation is always used and trailing zeros are preserved.
-
nawfal over 5 yearsDownvoting. This will turn 20 into 2 :/
-
user2091150 over 4 yearsGreat. Except for SqlDecimal it is CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator despite regional settings.