Reputation: 2475
I think I've found something that can't be done with formatting strings alone: I'm needing a string that would allow me to format a double to show no decimals and so that:
I've arrived to this.
"{0:#,0;(#,0);-}"
But, this is showing those numbers between (-0.5 and 0.5) as "-". If I replace it with the following.
"{0:#,0.#;(#,0.#);-}"
This works "ok", except that it'll show numbers with decimal points, and I need them rounded.
For illustration purposes, I've tried with:
string format = "#,0;(#,0);-";
Console.WriteLine(1000000.ToString(format));
Console.WriteLine(1000.ToString(format));
Console.WriteLine(100.ToString(format));
Console.WriteLine(10.ToString(format));
Console.WriteLine(1.ToString(format));
Console.WriteLine(0.5.ToString(format));
Console.WriteLine(0.4.ToString(format));
Console.WriteLine(0.ToString(format));
Console.WriteLine((-0.4).ToString(format));
Console.WriteLine((-0.5).ToString(format));
Console.WriteLine((-1).ToString(format));
Console.WriteLine((-1000000).ToString(format));
Which gives:
1,000,000
1,000
100
10
1
1
-
-
-
(1)
(1)
(1,000,000)
And:
string format = "#,0.#;(#,0.#);-";
Console.WriteLine(1000000.ToString(format));
Console.WriteLine(1000.ToString(format));
Console.WriteLine(100.ToString(format));
Console.WriteLine(10.ToString(format));
Console.WriteLine(1.ToString(format));
Console.WriteLine(0.5.ToString(format));
Console.WriteLine(0.4.ToString(format));
Console.WriteLine(0.ToString(format));
Console.WriteLine((-0.4).ToString(format));
Console.WriteLine((-0.5).ToString(format));
Console.WriteLine((-1).ToString(format));
Console.WriteLine((-1000000).ToString(format));
Which outputs:
1,000,000
1,000
100
10
1
0.5
0.4
-
(0.4)
(0.5)
(1)
(1,000,000)
But this is what I'm trying to achieve:
1,000,000
1,000
100
10
1
1
0
-
(0)
(1)
(1)
(1,000,000)
So I'm settling for using the first format string and then re-processing those values that come out as "-", but I wonder if there's a way to do this with the format string alone.
Thanks for any help!
Upvotes: 4
Views: 860
Reputation: 28611
Can this be done with formatting strings alone?
No.
https://msdn.microsoft.com/en-us/library/0c899ak8%28v=vs.110%29.aspx#SectionSeparator
Three sections
The first section applies to positive values, the second section applies to negative values, and the third section applies to zeros.
If the number to be formatted is nonzero, but becomes zero after rounding according to the format in the first or second section, the resulting zero is formatted according to the third section.
(added emphasis)
As I read that, it doesn't seem to be possible, using a single format string, to ever get both a "0" and a "-" in the same set of outputs (with only the values changing). "0" will use the third format which you want to be "-".
Rather than just say 'no' - what can be done? Have you considered creating a method to output in the format you need?
You can do this with an extension method:
public static string ToStringZeroDash(this decimal value, string format)
{
return value == 0 ? "-" : value.ToString(format);
}
example
(0.4).ToStringZeroDash("{0:#,0.#;(#,0.#);0}")
note the third part of the format is 0, but the extension returns "-" before it gets to there.
Edit: you might need (this double value ..
or whatever the actual value type is and you could make the format optional/overloads using a default.
Edit: the above edit was to show I did read the question... I always use decimal
so that floating point calculations are not an issue, which they can be as pointed out by weston in the comments. For completeness, here's a version for double
:
public static string ToStringZeroDash(this double value, string format)
{
const double tolerance = 0.0001;
return Math.Abs(value) < tolerance ? "-" : value.ToString(format);
}
change tolerance (some call this 'epsilon') as required.
Upvotes: 2