2010-06-23 2 views
77

Есть ли форматор отображения, который будет выводить десятичные числа в виде этих строковых представлений в C# без округления?Лучший способ отображения десятичного числа без конечных нулей

// decimal -> string 

20 -> 20 
20.00 -> 20 
20.5 -> 20.5 
20.5000 -> 20.5 
20.125 -> 20.125 
20.12500 -> 20.125 
0.000 -> 0 

{0} # будет круглым, и используя некоторые функции подрезки типа не будет работать с присоединенным числового столбца в сетке.

ответ

111

У вас есть максимальное количество знаков после запятой, которые вам когда-либо понадобится для отображения? (Ваши примеры имеют максимум 5).

Если это так, я думаю, что форматирование с помощью «0. #####» будет делать то, что вы хотите. Метод

static void Main(string[] args) 
    { 
     var dList = new decimal[] { 20, 20.00m, 20.5m, 20.5000m, 20.125m, 20.12500m, 0.000m }; 

     foreach (var d in dList) 
      Console.WriteLine(d.ToString("0.#####")); 
    } 
+4

И вы всегда можете бросить непомерную * количество символов # в формате. * не научный –

+2

+1 - кстати, вам не нужен ведущий #. «0. #####» работает одинаково. И так или иначе, это округляется от нуля (только FYI). – TrueWill

+0

Спасибо, просто пришлось использовать это! –

4

Расширение:

public static class Extensions 
{ 
    public static string TrimDouble(this string temp) 
    { 
     var value = temp.IndexOf('.') == -1 ? temp : temp.TrimEnd('.', '0'); 
     return value == string.Empty ? "0" : value; 
    } 
} 

Пример кода:

double[] dvalues = {20, 20.00, 20.5, 20.5000, 20.125, 20.125000, 0.000}; 
foreach (var value in dvalues) 
    Console.WriteLine(string.Format("{0} --> {1}", value, value.ToString().TrimDouble())); 

Console.WriteLine("=================="); 

string[] svalues = {"20", "20.00", "20.5", "20.5000", "20.125", "20.125000", "0.000"}; 
foreach (var value in svalues) 
    Console.WriteLine(string.Format("{0} --> {1}", value, value.TrimDouble())); 

Выход:

20 --> 20 
20 --> 20 
20,5 --> 20,5 
20,5 --> 20,5 
20,125 --> 20,125 
20,125 --> 20,125 
0 --> 0 
================== 
20 --> 20 
20.00 --> 2 
20.5 --> 20.5 
20.5000 --> 20.5 
20.125 --> 20.125 
20.125000 --> 20.125 
0.000 --> 0 
+1

"20.00 -> 2" Я думаю, что это нехорошее поведение. Чтобы исправить это, вызовите TrimEnd два раза: TrimEnd ('0'); TrimEnd (''); – Vadim

+2

НЕ ИСПОЛЬЗУЙТЕ код, указанный выше. @VadymK правильно, что его поведение ошибочно. Он будет обрезать конечные нули, которые до периода, если нет периода. – Sevin7

+1

Ответы на stackoverflow не для копирования-вставки. Они используются как источник *** обучения ***. Этот код sampel учит вас использовать 'IndexOf' для поиска символов внутри строки. Очень легко настроить пример, чтобы решить проблему без десятичных знаков. – jgauffin

1

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

public static string TrimDecimal(decimal value) 
{ 
    string result = value.ToString(System.Globalization.CultureInfo.InvariantCulture); 
    if (result.IndexOf('.') == -1) 
     return result; 

    return result.TrimEnd('0', '.'); 
} 
+0

не будет работать с «0.0» =) – jgauffin

3

Это довольно легко сделать из коробки:

Decimal YourValue; //just as example 
String YourString = YourValue.ToString().TrimEnd('0','.'); 

, который удаляет все конечные нули от вашего Decimal.

Единственное, что вам нужно сделать, это добавить .ToString().TrimEnd('0','.'); в десятичную переменную, чтобы преобразовать десятичную строку в строку без конечных нулей, как в приведенном выше примере.

В некоторых регионах она должна быть .ToString().TrimEnd('0',','); (где они нас запятая вместо точки, но вы также можете добавить точку и запятую в качестве параметров, чтобы убедиться)

(вы можете также добавить и как параметры)

+0

Вы можете не осознавать этого, но при работе с аргументом 'params' вам не нужно явно строить массив. Поэтому вместо подробного 'TrimEnd (" 0 ".ToCharArray()) вы можете просто написать' TrimEnd ('0') '(примечание: передано одиночное' char' вместо 'char []'). –

+0

@ Дань Тао: Спасибо, я забыл об этом. Прошло некоторое время с тех пор, как я использовал C#. Хотя обе версии работают, я редактировал свой пост. – Mervin

+0

@Mervin: Вам нужно передать 'char', а не' string' (так: одинарные кавычки, а не двойные кавычки). Я исправил это для вас - надеюсь, вы не против. –

14

Этот формат строки должен сделать ваш день: «0. #############################». Имейте в виду, что десятичные знаки могут иметь не более 29 значащих цифр.

Примеры:

? (1000000.00000000000050000000000m).ToString("0.#############################") 
-> 1000000.0000000000005 

? (1000000.00000000000050000000001m).ToString("0.#############################") 
-> 1000000.0000000000005 

? (1000000.0000000000005000000001m).ToString("0.#############################") 
-> 1000000.0000000000005000000001 

? (9223372036854775807.0000000001m).ToString("0.#############################") 
-> 9223372036854775807 

? (9223372036854775807.000000001m).ToString("0.#############################") 
-> 9223372036854775807.000000001 
+0

Это самый общий ответ на эту проблему. Не уверен, почему это не стандартный формат «G» для десятичного. Конечные нули не добавляют никакой информации. Документация Microsoft имеет странное предостережение для десятичного числа: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#GFormatString Однако, если число Десятичный и спецификатор точности опущены, нотация фиксированной точки всегда используется, и сохраняются нулевые нули. –

18

Я только что узнал, как правильно использовать формат G спецификатор. См. MSDN Documentation. Существует небольшая заметка, указывающая, что конечные нули будут сохраняться для десятичных типов, если не задана точность. Почему они это сделают, я не знаю, но указание максимального количества цифр для нашей точности должно исправить эту проблему. Таким образом, для форматирования десятичных знаков наилучшим вариантом является G29.

decimal test = 20.5000m; 
test.ToString("G"); // outputs 20.5000 like the documentation says it should 
test.ToString("G29"); // outputs 20.5 which is exactly what we want 
+14

Это приведет к 0,00001, отображаемому как 1E-05, хотя – sehe

7

Это еще одна вариация того, что я видел выше. В моем случае мне нужно сохранить все значащие цифры справа от десятичной точки, что означает падение всех нулей после самой значащей цифры. Просто подумал, что было бы приятно поделиться. Я не могу ручаться за эффективность этого, хотя, но когда вы пытаетесь достичь эстетики, вы уже в значительной степени прокляты неэффективностью.

public static string ToTrimmedString(this decimal target) 
{ 
    string strValue = target.ToString(); //Get the stock string 

    //If there is a decimal point present 
    if (strValue.Contains(".")) 
    { 
     //Remove all trailing zeros 
     strValue = strValue.TrimEnd('0'); 

     //If all we are left with is a decimal point 
     if (strValue.EndsWith(".")) //then remove it 
      strValue = strValue.TrimEnd('.'); 
    } 

    return strValue; 
} 

Вот и все, просто хотел выбросить мои два цента.

+1

Это простое решение, оно не взорвется и для «0.0». Я добавил флаг по умолчанию, чтобы целые числа отображались как «1.0», и это только что привело к тому, что все мои десятичные числа попали в линию. Не могу понять, почему это не лучший ответ + лоты. –

+1

Это особенно хорошо, если кто-то уже передал вам строку. Вы можете просто изменить его на ToTrimmedString (эта строка strValue) и удалить первую строку. – PRMan

+0

Это хороший момент. Я думаю, когда я писал это, я имел дело с ценностями, которые были уже десятичными знаками или чем-то таким, поэтому я хотел охватить все это.Вместо этого вы можете использовать тело этого метода внутри другого перегруженного метода, который вместо этого принимает строку. – dyslexicanaboko

1
decimal val = 0.000000000100m; 
string result = val == 0 ? "0" : val.ToString().TrimEnd('0').TrimEnd('.'); 
+3

И когда число равно 2000, это будет печатать 2, поэтому ... –

+1

Спасибо, Сами, я только что обновил свое решение. –

3

Другое решение, основанное на dyslexicanaboko's ответ, но не зависит от текущей культуры:

public static string ToTrimmedString(this decimal num) 
{ 
    string str = num.ToString(); 
    string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; 
    if (str.Contains(decimalSeparator)) 
    { 
     str = str.TrimEnd('0'); 
     if(str.EndsWith(decimalSeparator)) 
     { 
      str = str.RemoveFromEnd(1); 
     } 
    } 
    return str; 
} 

public static string RemoveFromEnd(this string str, int characterCount) 
{ 
    return str.Remove(str.Length - characterCount, characterCount); 
} 
0

я закончил с помощью следующего кода:

public static string DropTrailingZeros(string test) 
    { 
     if (test.Contains(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)) 
     { 
      test = test.TrimEnd('0'); 
     } 

     if (test.EndsWith(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)) 
     { 
      test = test.Substring(0, 
       test.Length - CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator.Length); 
     } 

     return test; 
    }