Лучший способ отображения десятичной дроби без конечных нулей - PullRequest
93 голосов
/ 23 июня 2010

Существует ли средство форматирования отображения, которое будет выводить десятичные дроби в виде этих строковых представлений в 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. #} будет округляться, и использование некоторой функции типа Trim не будет работать ссвязанный числовой столбец в сетке.

Ответы [ 11 ]

132 голосов
/ 23 июня 2010

У вас есть максимальное количество десятичных разрядов, которое вам когда-либо нужно отображать?(Ваши примеры имеют максимум 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.#####"));
    }
29 голосов
/ 30 декабря 2011

Я только что узнал, как правильно использовать спецификатор формата G. См. Документация MSDN . Внизу есть примечание, в котором говорится, что конечные нули будут сохраняться для десятичных типов, если не указана точность. Почему они это делают, я не знаю, но указание максимального количества цифр для нашей точности должно решить эту проблему. Так что для форматирования десятичных дробей, 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
15 голосов
/ 11 сентября 2011

Этот формат строки должен сделать ваш день: "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
9 голосов
/ 18 октября 2012

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

4 голосов
/ 23 июня 2010

Метод расширения:

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
3 голосов
/ 18 июля 2016

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

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);
}
2 голосов
/ 23 июня 2010

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

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

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

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

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

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

1 голос
/ 23 июня 2010

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

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 голосов
/ 26 декабря 2018

У меня получился такой вариант:

public static string Decimal2StringCompact(decimal value, int maxDigits)
    {
        if (maxDigits < 0) maxDigits = 0;
        else if (maxDigits > 28) maxDigits = 28;
        return Math.Round(value, maxDigits, MidpointRounding.ToEven).ToString("0.############################", CultureInfo.InvariantCulture);
    }

Преимущества:

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

вы можете явно указать метод округления;

вы можете явно контролировать культуру.

0 голосов
/ 09 июня 2017

Я получил следующий код:

    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;
    }
...