Форматирование как строка в C#

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
0
19 116
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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();

Другие вопросы по теме