Може ли това да се направи само с форматиращи низове?

Мисля, че открих нещо, което не може да се направи само с форматиране на низове: имам нужда от низ, който би ми позволил да форматирам двойно, за да не показва десетични знаци и така че:

  • Числата са разделени от хиляди
  • 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, така че изчисленията с плаваща запетая да не са проблем, което може да бъде, както е посочено от weston в коментарите. За пълнота, ето версия за 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