У меня есть Double, значение которого может составлять от 0,000001 до 1 000 000 000 000.
Я хочу отформатировать это число как строку, но условно в зависимости от его размера. Поэтому, если он очень маленький, я хочу отформатировать его примерно так:
String.Format("{0:.000000000}", number);
если он не такой маленький, скажем 0,001, тогда я хочу использовать что-то вроде
String.Format("{0:.00000}", number);
и если он закончился, скажем 1000, отформатируйте его как:
String.Format("{0:.0}", number);
Есть ли умный способ построить эту строку формата на основе размера значения, которое я собираюсь форматировать?





Используйте символ # для необязательных позиций в строке:
string.Format("{0:#,###,##0.000}", number);
Я не думаю, что вы можете контролировать количество таких десятичных знаков, поскольку точность двойного числа, скорее всего, все испортит.
Чтобы инкапсулировать логику определения количества десятичных знаков для вывода, вы можете создать собственный модуль форматирования.
Используйте Math.Log10 абсолютного значения числа double, чтобы выяснить, сколько нулей вам нужно слева (если положительное) или справа (если отрицательное) от десятичного разряда. Выберите строку формата на основе этого значения. Вам потребуется обрабатывать нулевые значения отдельно.
string s;
double epislon = 0.0000001; // or however near zero you want to consider as zero
if (Math.Abs(value) < epislon) {
int digits = Math.Log10( Math.Abs( value ));
// if (digits >= 0) ++digits; // if you care about the exact number
if (digits < -5) {
s = string.Format( "{0:0.000000000}", value );
}
else if (digits < 0) {
s = string.Format( "{0:0.00000})", value );
}
else {
s = string.Format( "{0:#,###,###,##0.000}", value );
}
}
else {
s = "0";
}
Или создайте его динамически на основе количества цифр.
Первые два String.Format в вашем вопросе можно решить, автоматически удалив конечные нули:
String.Format("{0:#,##0.########}", number);
И последний, который вы могли решить, вызвав Math.Round (number, 1) для значений более 1000, а затем используйте тот же String.Format.
Что-то типа:
String.Format("{0:#,##0.########}", number<1000 ? number : Math.Round(number,1));
Если бы это был я, я бы написал собственный класс-оболочку и поместил бы код tvanfosson в его метод ToString. Таким образом, вы все еще можете работать с двойным значением, но вы получите правильное строковое представление практически во всех случаях. Это выглядело бы примерно так:
class FormattedDouble
{
public double Value { get; set; }
protected overrides void ToString()
{
// tvanfosson's code to produce the right string
}
}
Может быть, было бы лучше сделать это структурой, но я сомневаюсь, что это будет иметь большое значение. Вы можете использовать этот класс так:
var myDouble = new FormattedDouble();
myDouble.Value = Math.Pi;
Console.WriteLine(myDouble);
В продолжение OwenP (и, по его словам, tvanfosson):
Если он достаточно распространен, и вы используете C# 3.0, я бы превратил его в метод расширения для double:
class MyExtensions
{
public static string ToFormmatedString(this double d)
{
// Take d and implement tvanfosson's code
}
}
Теперь везде, где у вас есть дублер, вы можете:
double d = 1.005343;
string d_formatted = d.ToFormattedString();