Можно ли это сделать только с помощью строк форматирования?

Я думаю, что нашел что-то, что нельзя сделать только с форматированием строк: мне нужна строка, которая позволила бы мне отформатировать двойное число, чтобы не отображались десятичные знаки, и чтобы:

  • Числа разделены тысячами
  • 0 показывает тире
  • Отрицательные числа показаны между скобками
  • 0,5 округляется до 1, а -0,5 до -1.
  • 0,4999... округляется до 0, а -0,4999... до -0 (что должно отображаться как "(0)").

Я пришел к этому.

"{0:#,0;(#,0);-}"

Но это показывает эти числа между (-0,5 и 0,5) как «-». Если я заменю его следующим.

"{0:#,0.#;(#,0.#);-}"

Это работает «хорошо», за исключением того, что числа будут отображаться с десятичными точками, а мне нужно, чтобы они были округлены.

Для иллюстрации я пробовал:

string format = "#,0;(#,0);-";

Console.WriteLine(1000000.ToString(format));
Console.WriteLine(1000.ToString(format));
Console.WriteLine(100.ToString(format));
Console.WriteLine(10.ToString(format));
Console.WriteLine(1.ToString(format));
Console.WriteLine(0.5.ToString(format));
Console.WriteLine(0.4.ToString(format));
Console.WriteLine(0.ToString(format));
Console.WriteLine((-0.4).ToString(format));
Console.WriteLine((-0.5).ToString(format));
Console.WriteLine((-1).ToString(format));
Console.WriteLine((-1000000).ToString(format));

Который дает:

1,000,000
1,000
100
10
1
1
-
-
-
(1)
(1)
(1,000,000)

А также:

string format = "#,0.#;(#,0.#);-";

Console.WriteLine(1000000.ToString(format));
Console.WriteLine(1000.ToString(format));
Console.WriteLine(100.ToString(format));
Console.WriteLine(10.ToString(format));
Console.WriteLine(1.ToString(format));
Console.WriteLine(0.5.ToString(format));
Console.WriteLine(0.4.ToString(format));
Console.WriteLine(0.ToString(format));
Console.WriteLine((-0.4).ToString(format));
Console.WriteLine((-0.5).ToString(format));
Console.WriteLine((-1).ToString(format));
Console.WriteLine((-1000000).ToString(format));

Что выводит:

1,000,000
1,000
100
10
1
0.5
0.4
-
(0.4)
(0.5)
(1)
(1,000,000)

Но это то, чего я пытаюсь достичь:

1,000,000
1,000
100
10
1
1
0
-
(0)
(1)
(1)
(1,000,000)

Итак, я соглашаюсь использовать первую строку формата, а затем повторно обрабатывать те значения, которые выводятся как «-», но мне интересно, есть ли способ сделать это только с помощью строки формата.

Спасибо за любую помощь!


person Sebastián Vansteenkiste    schedule 07.05.2015    source источник
comment
Какой результат вы на самом деле ищете?   -  person Greg    schedule 07.05.2015
comment
Вот еще одна идея. Заранее выполните округление отдельно и используйте более простое форматирование строк. Очевидно, что речь идет не только о строках формата.   -  person ryanyuyu    schedule 07.05.2015
comment
Я точно пояснил, чего я пытаюсь достичь сейчас, спасибо @Greg. И да, ryanyuyu, я думал об этом, но у меня большие успехи в том, чтобы заставить (0) появляться таким образом.   -  person Sebastián Vansteenkiste    schedule 07.05.2015
comment
0 показывает прочерк, что такое ноль? только целые нули?   -  person weston    schedule 07.05.2015
comment
Привет @weston, я уже пояснил, чего я пытался добиться, и получил ответ, которого ожидал. Еще спасибо.   -  person Sebastián Vansteenkiste    schedule 07.05.2015


Ответы (1)


Можно ли это сделать только с помощью строк форматирования?

No.

https://msdn.microsoft.com/en-us/library/0c899ak8%28v=vs.110%29.aspx#SectionSeparator

Три раздела

Первый раздел применяется к положительным значениям, второй раздел — к отрицательным значениям, и третий раздел — к нулям.

Если форматируемое число не равно нулю, но становится равным нулю после округления в соответствии с форматом в первом или втором разделе, результирующий нуль форматируется в соответствии с третьим разделом.

(добавлен акцент)

Когда я это прочитал, кажется невозможным, используя одну строку формата, когда-либо получить оба "0" и "-" в одном и том же наборе выходных данных (только с значения меняются). «0» будет использовать третий формат, который вы хотите использовать «-».

Вместо того, чтобы просто сказать «нет» — что можно сделать? Рассматривали ли вы создание метода для вывода в нужном вам формате?

Вы можете сделать это с помощью метода расширения:

public static string ToStringZeroDash(this decimal value, string format)
{
    return value == 0 ? "-" : value.ToString(format);
}

пример

(0.4).ToStringZeroDash("{0:#,0.#;(#,0.#);0}")

обратите внимание, что третья часть формата равна 0, но расширение возвращает «-», прежде чем оно доберется туда.

Изменить: вам может понадобиться (this double value .. или любой другой фактический тип значения, и вы можете сделать формат необязательным/перегружаться, используя значение по умолчанию.

Редактировать: приведенное выше редактирование должно было показать, что я действительно прочитал вопрос ... Я всегда использую decimal, чтобы вычисления с плавающей запятой не были проблемой, на что они могут быть, как указал Уэстон в комментариях. Для полноты картины вот версия для double:

public static string ToStringZeroDash(this double value, string format)
{
    const double tolerance = 0.0001;
    return Math.Abs(value) < tolerance ? "-" : value.ToString(format);
}

изменить допуск (некоторые называют это «эпсилон») по мере необходимости.

person freedomn-m    schedule 07.05.2015
comment
If the number to be formatted is nonzero, but becomes zero after rounding according to the format in the first or second section, the resulting zero is formatted according to the third section. Ой! Я не читал этот абзац, когда смотрел документы. Да, я придумал собственную функцию форматирования для особых случаев. Спасибо! - person Sebastián Vansteenkiste; 07.05.2015
comment
Удалено мое голосование из-за комментария о double. Вы не хотите сравнивать двойников с 0, используя == - person weston; 07.05.2015