To do this, you definitely need to create your own formatter.
To create a custom formatter, here is what you should know:
string.Format
has the following overload: string.Format(IFormatProvider, string, object[])
, so you must create an IFormatProvider
that will "provide" ICustomFormatter
that will handle your custom formatting. The same class can be easily used for both interfaces.
Here is some code that does exactly what you describe:
public class DoubleFormatter : IFormatProvider, ICustomFormatter { // Implementation of IFormatProvider: public object GetFormat(Type t) { if (t == typeof(ICustomFormatter)) { return this; } return null; } // Implementation of ICustomFormatter: public string Format(string format, object arg, IFormatProvider provider) { // Search for the custom "EE" format specifier: if (format == null || !format.StartsWith("EE")) return null; format = format.Substring(2); // Trim "EE" // Determine how many digits before we cutoff: int digits; if (!int.TryParse(format, out digits)) { throw new FormatException("Format must contain digits"); } // Get the value: (note, this will work for any numeric type) var value = Convert.ToDouble(arg); // Convert to string without using Exponential format: var output = value.ToString("0."+(new string('#',digits)), provider); // Determine how many digits are showing: (this part isn't culture-compatible) var length = output.Length - output.IndexOf("."); if (length <= digits) { return output; } else { return value.ToString("E"+format, provider); } } }
And here is an example of using this code:
var tests = new[]{ 0.0000055555, 0.00000555555555555555555, }; var formatter = new DoubleFormatter(); foreach (var t in tests){ var result = string.Format(formatter, "{0:EE15}", t); Console.WriteLine(result); }
source share