Форматирование двойной как строка в C # - PullRequest
9 голосов
/ 10 декабря 2008

У меня есть 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);

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

Ответы [ 5 ]

15 голосов
/ 10 декабря 2008

Используйте Math.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";
}

Или построить его динамически на основе количества цифр.

2 голосов
/ 11 апреля 2009

Вслед за OwenP (и "расширением" tvanfosson):

Если это достаточно распространено, и вы используете C # 3.0, я бы превратил его в метод расширения на двойном:

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();
2 голосов
/ 10 декабря 2008

Первые два String.Format в вашем вопросе могут быть решены путем автоматического удаления конечных нулей:

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

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

Что-то вроде:

String.Format("{0:#,##0.########}", number<1000 ? number : Math.Round(number,1));
2 голосов
/ 10 декабря 2008

Используйте символ # для необязательных позиций в строке:

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

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

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

1 голос
/ 11 декабря 2008

Если бы это был я, я бы написал собственный класс-обертку и поместил код 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...