Форматирование double as string в C#

у меня есть двойной, который может иметь значение от 0,000001 до 1,000,000,000.000

Я хочу отформатировать это число как строку, но условно в зависимости от ее размера. Поэтому, если он очень маленький, я хочу отформатировать его с помощью чего-то вроде:

String.Format("{0:.000000000}", number);

если это не так мало, скажем, 0.001, то я хочу использовать что-то вроде

String.Format("{0:.00000}", number);

и если это закончилось, скажем, 1,000, затем отформатируйте его как:

String.Format("{0:.0}", number);

есть ли умный способ построить это форматировать строку на основе размера значения, которое я собираюсь форматировать?

5 ответов


Использовать Математику.Log10 абсолютного значения double, чтобы выяснить, сколько 0 вам нужно либо слева (если положительный), либо справа (если отрицательный) десятичного знака. Выберите строку формата на основе этого значения. Вам нужно будет обрабатывать нулевые значения отдельно.

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("{0:#,###,##0.000}", number);

Я не думаю, что вы можете контролировать количество десятичных знаков, как это, как точность двойника, вероятно, испортит вещи.

чтобы инкапсулировать логику определения количества десятичных знаков для вывода, вы можете посмотреть на создание пользовательского форматирования.


первые две строки.Формат в вашем вопросе можно решить, автоматически удалив конечные нули:

String.Format("{0:#,##0.########}", number);

и последний, который вы могли бы решить, вызвав Math.Round (number, 1) для значений более 1000, а затем используйте ту же строку.Формат.

что-то типа:

String.Format("{0:#,##0.########}", number<1000 ? number : Math.Round(number,1));

Последующие действия по 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();

если бы это был я, я бы написал пользовательский класс-оболочку и поместил код 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);