후행 0없이 소수점을 표시하는 가장 좋은 방법


107

반올림하지 않고 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. #}은 반올림되며 일부 트림 유형 함수를 사용하면 그리드의 바인딩 된 숫자 열에서 작동하지 않습니다.

답변:


147

표시해야 할 소수점 이하 자릿수가 최대입니까? (귀하의 예제는 최대 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
그리고 항상 형식에 엄청난 수의 # 기호를 던질 수 있습니다. * 과학이 아님
Anthony Pegram

3
+1-부수적으로 선행 #이 필요하지 않습니다. "0. #####"은 동일하게 작동합니다. 그리고 어느 쪽이든, 이것은 0에서 반올림합니다 (참고로).
TrueWill

14
@TrueWill 실제로 그것은 차이를 만듭니다. d == 0.1m이면 "0. #"은 "0.1"을 렌더링하고 "#. #"은 앞에 0이없는 ".1"을 렌더링합니다. 둘 다 틀리거나 옳지 않고 원하는 것에 따라 다릅니다.
AaronLS 2012

4
항상 소수점 하나를 표시해야했기 때문에 문자열 형식을 사용했습니다 "0.0#".
해머와 함께 코드

1
아래 Erwin Mayer의 답변을 참조하십시오.
shlgug

32

G형식 지정자 를 올바르게 사용하는 방법을 방금 배웠습니다 . MSDN 문서를 참조하십시오 . 정밀도가 지정되지 않은 경우 10 진수 유형에 대해 후행 0이 보존된다는 메모가 약간 있습니다. 그들이 이것을하는 이유는 모르겠지만 정밀도에 대한 최대 자릿수를 지정하면 문제가 해결됩니다. 따라서 소수 형식을 지정 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

21
그래도 0.00001이 1E-05로 표시됩니다
sehe

17

이 문자열 형식은 "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

4
이것이 문제에 대한 가장 일반적인 대답입니다. 이것이 십진수의 기본 "G"형식이 아닌 이유를 잘 모르겠습니다. 후행 0은 정보를 추가하지 않습니다. Microsoft 설명서에는 10 진수에 대한 이상한주의 사항이 있습니다. docs.microsoft.com/en-us/dotnet/standard/base-types/… 그러나 숫자가 Decimal이고 정밀도 지정자가 생략 된 경우 고정 소수점 표기법이 항상 사용됩니다. 후행 0은 보존됩니다.
Eric Roller

10

이것은 위에서 본 것의 또 다른 변형입니다. 제 경우에는 소수점 오른쪽에있는 모든 유효 자릿수를 보존해야합니다. 즉, 최상위 자릿수 뒤에있는 모든 0을 삭제합니다. 공유하는 것이 좋을 것이라고 생각했습니다. 나는 이것의 효율성을 보증 할 수는 없지만 미학을 얻으려고 할 때 이미 비 효율성에 거의 휩싸입니다.

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

그게 다야, 그냥 내 2 센트를 던지고 싶었어.


3
이것은 쉽게 최상의 솔루션이며 "0.0"에 대해서도 폭발하지 않습니다. 정수가 선택적으로 "1.0"으로 표시되도록 기본 플래그를 추가했으며 이로 인해 모든 소수가 줄에 들어갔습니다. 이것이 왜 최선의 답이 아닌지 이해할 수 없습니다.
Steve Hibbert 2014 년

2
누군가 이미 문자열을 전달한 경우 특히 좋습니다. ToTrimmedString (this string strValue)로 변경하고 첫 번째 줄을 제거 할 수 있습니다.
PRMan 2017 년

그건 좋은 지적이야. 이 글을 쓸 때 이미 십진수 등의 값을 다루고 있었기 때문에 전체를 포괄하고 싶었습니다. 대신 문자열을받는 다른 오버로드 된 메서드 내부에 해당 메서드의 본문을 가질 수 있습니다.
dyslexicanaboko

ToTrimmedString ()을 호출 할 수있는 경우 좋은 솔루션이지만 형식 문자열로 제한되는 경우가 많습니다.
Mike Marynowski

1
소수 구분자는 문화에 따라 다르지만 이것이 좋은 해결책이라고 생각합니다. 수표 strValue.TrimEnd('0').TrimEnd('.')대신 왜 EndsWith안되는가?
nawfal 19 dec

5

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

큰. SqlDecimal을 제외하고는 지역 설정에도 불구하고 CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator입니다.
user2091150

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 2014

2
위에 쓰여진 코드를 사용하지 마십시오. @VadymK는 그 동작에 결함이 있다는 것이 정확합니다. 마침표가없는 경우 마침표 이전의 후행 0을 자릅니다.
Sevin7

2
stackoverflow에 대한 답변은 복사-붙여 넣기를위한 것이 아닙니다. 그것들은 학습 의 원천으로 사용됩니다 . 이 샘플 코드는 IndexOf문자열 내에서 문자를 찾는 데 사용 하는 방법 을 알려줍니다 . 소수없이 문제를 해결하기 위해 예제를 조정하는 것은 매우 쉽습니다.
jgauffin 2016-06-25

2

나는 그것이 즉시 가능하다고 생각하지 않지만 이와 같은 간단한 방법으로 할 수 있습니다.

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

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

2

상자에서 꺼내는 것은 매우 쉽습니다.

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

Decimal에서 모든 후행 0을 제거합니다.

당신이해야 할 유일한 일은 위의 예와 같이 .ToString().TrimEnd('0','.');소수점 변수에 추가 하여 Decimala String를 후행 0없이 로 변환하는 것입니다.

일부 지역에서는 a .ToString().TrimEnd('0',',');(점 대신 쉼표를 사용하지만 확인을 위해 점과 쉼표를 매개 변수로 추가 할 수도 있음) 여야합니다.

(둘 다 매개 변수로 추가 할 수도 있습니다)


이것을 깨닫지 못할 수도 있지만 params인수를 다룰 때 명시 적으로 배열을 구성 할 필요는 없습니다. 따라서 자세한 정보 대신 TrimEnd("0".ToCharArray())쓸 수 있습니다 TrimEnd('0')(참고 : chara 대신 단일 전달됨 char[]).
Dan Tao

@Dan Tao : 고마워, 나는 그것을 잊었다. C #을 사용한 지 오래되었습니다. 두 버전 모두 작동하지만 내 게시물을 편집했습니다.
Mervin

@Mervin : a가 아닌를 전달해야 char합니다 string(따라서 큰 따옴표가 아니라 작은 따옴표). 나는 당신을 위해 그것을 고쳤습니다.
Dan Tao

1
솔루션은 "2"와 같은 출력을 생성합니다. 0 만있을 때.
jgauffin

2
그런 다음 .ToString (). TrimEnd ( '0'). TrimEnd ( '.')를 호출하는 것이 좋습니다. 또한 '.'대신 CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator를 사용하는 것이 더 좋습니다. 그래야 여러 문화권에서 작동합니다.
Ε Г И І И О

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

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

0

이 변종으로 끝났습니다.

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

확장 방법을 만들 수 있습니다.

public static class ExtensionMethod {
  public static decimal simplify_decimal(this decimal value) => decimal.Parse($"{this:0.############}");
}

0

내 프로젝트 중 하나에 맞게 아래 확장 방법을 만들었지 만 다른 사람에게 도움이 될 수도 있습니다.

using System.Numerics;
using System.Text.RegularExpressions;
internal static class ExtensionMethod
{
    internal static string TrimDecimal(this BigInteger obj) => obj.ToString().TrimDecimal();
    internal static string TrimDecimal(this decimal obj) => new BigInteger(obj).ToString().TrimDecimal();
    internal static string TrimDecimal(this double obj) => new BigInteger(obj).ToString().TrimDecimal();
    internal static string TrimDecimal(this float obj) => new BigInteger(obj).ToString().TrimDecimal();
    internal static string TrimDecimal(this string obj)
    {
        if (string.IsNullOrWhiteSpace(obj) || !Regex.IsMatch(obj, @"^(\d+([.]\d*)?|[.]\d*)$")) return string.Empty;
        Regex regex = new Regex("^[0]*(?<pre>([0-9]+)?)(?<post>([.][0-9]*)?)$");
        MatchEvaluator matchEvaluator = m => string.Concat(m.Groups["pre"].Length > 0 ? m.Groups["pre"].Value : "0", m.Groups["post"].Value.TrimEnd(new[] { '.', '0' }));
        return regex.Replace(obj, matchEvaluator);
    }
}

에 대한 참조가 필요하지만 System.Numerics.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.