문자열 형식을 사용하여 소수점 이하 2 자리 또는 간단한 정수 표시


291

때로는 100 또는 100.99 또는 100.9 일 수있는 가격 필드가 표시됩니다. 원하는 것은 해당 가격에 소수를 입력 한 경우에만 소수점 이하 2 자리로 가격을 표시하는 것입니다. 예를 들어 100 인 경우에만 100을 100.00이 아니라 100으로 표시하고 가격이 100.2 인 경우 100.22와 유사하게 100.20을 표시해야합니다. 나는 googled하고 몇 가지 예를 보았지만 원하는 것과 정확히 일치하지 않았다.

// just two decimal places
String.Format("{0:0.00}", 123.4567);      // "123.46"
String.Format("{0:0.00}", 123.4);         // "123.40"
String.Format("{0:0.00}", 123.0);         // "123.00"


1
RE : "원하는 것은 가격에 소수점을 입력 한 경우에만 소수점 2 자리로 가격을 표시하는 것입니다."-사용자가 "100.00"을 입력하면 "100.00"을 표시하려고하지만 "100"을 입력하면 "100"만 표시하고 싶습니까? -숫자 유형은 숫자 값만 추적합니다. 사용자가 입력 한 중요하지 않은 숫자와 그렇지 않은 숫자는 문자열을 사용해야합니다.
BrainSlugs83

2
@BinaryWorrier 나는이 질문이 중복 될 수 있다고 생각하지만 훨씬 더 좋고 완전한 답변이 있습니다. 다른 하나는 IMO로 복제되어야합니다.
Ryan Gates

그냥 .Replace ( ". 00", "")를 추가하십시오
Dave Sumter

답변:


156

우아하지 않은 방법은 다음과 같습니다.

var my = DoFormat(123.0);

DoFormat같은되는 :

public static string DoFormat( double myNumber )
{
    var s = string.Format("{0:0.00}", myNumber);

    if ( s.EndsWith("00") )
    {
        return ((int)myNumber).ToString();
    }
    else
    {
        return s;
    }
}

우아하지는 않지만 일부 프로젝트의 비슷한 상황에서 나를 위해 일하고 있습니다.


6
이것은 실제로 묻는 질문은 아니지만 string.Format ( "{0 : 0.00}"). Replace ( ". 00", "")를 사용하지 않는 이유는 무엇입니까?
BrainSlugs83

18
@ BrainSlugs83 : 현재 스레드에 따라 CurrentCulture소수점 구분 기호가 아닐 수 있습니다 .. CultureInfo.InvariantCulture와 함께 사용 하지 않으면 string.Format의 값을 확인 CultureInfo.NumberFormat.NumberDecimalSeparator해야하며 실제 PITA가됩니다. :)
Groo

@Uwe Keim 내가 60000int를 가지고 있고 그것을 원한다면 60.000?
Prashant Pimpale

이 대답은 "사각 바퀴 재발견"의 경우입니다. 문화 또는 이것이 .NET에 의해 이미 처리되었다는 사실을 고려하지 않습니다.
bytedev

523

이 질문을 다시 활성화하여 죄송하지만 여기에서 정답을 찾지 못했습니다.

숫자 서식을 지정 0하면 필수 장소 및 #선택적 장소로 사용할 수 있습니다 .

그래서:

// just two decimal places
String.Format("{0:0.##}", 123.4567);      // "123.46"
String.Format("{0:0.##}", 123.4);         // "123.4"
String.Format("{0:0.##}", 123.0);         // "123"

0와 결합 할 수도 있습니다 #.

String.Format("{0:0.0#}", 123.4567)       // "123.46"
String.Format("{0:0.0#}", 123.4)          // "123.4"
String.Format("{0:0.0#}", 123.0)          // "123.0"

이 형식화 방법은 항상 사용됩니다 CurrentCulture. 일부 문화권의 .경우로 변경됩니다 ,.

원래 질문에 대한 답변 :

가장 간단한 솔루션은 @Andrew ( here ) 에서 제공됩니다 . 그래서 개인적으로 다음과 같은 것을 사용합니다.

var number = 123.46;
String.Format(number % 1 == 0 ? "{0:0}" : "{0:0.00}", number)

20
처음에는 원래 질문을 여러 번 다시 읽을 때까지 이것이 대답이어야한다고 생각했습니다. OP는 그가 정확히 원하는 것을 완전히 명확하지는 않지만 누군가 분수에 들어가면 항상 소수점 2 자리를 원하는 것 같습니다. 누군가가 1.1을 입력하면 1.10을 원할 것입니다. 이 코드는 그렇게하지 않을 것입니다.
더그 S

40
죄송합니다. 다시 읽습니다. 따라서 이것은 정답이 아니지만 적어도 누군가가 이것을 유용하게 사용할 수 있습니다.
Gh61

이를 통해 필요한 OP를 얻을 수 있습니다. stackoverflow.com/a/33180829/2321042
Andrew

방금 유용하고 그리드 뷰의 BoundField가 SqlDouble로 수행하는 형식과 일치하지 않는 것으로 나타났습니다. 표시 할 최대 값을 표시해야합니다. (BoundField 대, 원하는
만큼만 ​​보여줄 수있어 기쁘다

그렇습니다. 이것은 유용했지만 소수점이있는 경우 소수점 이하 두 자릿수 만 표시하는 방법은 무엇입니까? 즉, 정수라면 소수점을 표시하지 않습니까?
Nigel Fds

64

이것은 일반적인 형식의 부동 숫자 사용 사례입니다.

불행히도, 모든 내장 된 한 글자 형식 문자열 (예 : F, G, N)은이를 직접 달성하지 못합니다.
예를 들어 num.ToString("F2")항상 같은 소수점 이하 두 자리를 표시 123.40합니다.

0.##조금 자세하게 보이더라도 패턴 을 사용해야 합니다.

완전한 코드 예제 :

double a = 123.4567;
double b = 123.40;
double c = 123.00;

string sa = a.ToString("0.##"); // 123.46
string sb = b.ToString("0.##"); // 123.4
string sc = c.ToString("0.##"); // 123

7
그러나 그는 123.4가 아닌 123.40을 원합니다.
Andrew

8
이 질문을 해결하지 않고 내 것을 해결하십시오. 나는 이것을 다른 사람들이 볼 수 있도록 찬성했다.
Emad

46

오래된 질문이지만 내 의견으로는 가장 간단한 옵션을 추가하고 싶었습니다.

천 단위 구분 기호가 없는 경우 :

value.ToString(value % 1 == 0 ? "F0" : "F2")

천 단위 구분 :

value.ToString(value % 1 == 0 ? "N0" : "N2")

동일하지만,과 및 String.format :

String.Format(value % 1 == 0 ? "{0:F0}" : "{0:F2}", value) // Without thousands separators
String.Format(value % 1 == 0 ? "{0:N0}" : "{0:N2}", value) // With thousands separators

여러 곳 에서 필요한 경우 확장 방법 으로이 논리를 사용합니다 .

public static string ToCoolString(this decimal value)
{
    return value.ToString(value % 1 == 0 ? "N0" : "N2"); // Or F0/F2 ;)
}

28

시험

double myPrice = 123.0;

String.Format(((Math.Round(myPrice) == myPrice) ? "{0:0}" : "{0:0.00}"), myPrice);

5
string.Format ((숫자 % 1) == 0? "{0 : 0}": "{0 : 0.00}", 숫자);
Patrick

8

어쨌든 형식 지정자에 조건을 넣는 방법을 모르지만 자신의 포맷터를 작성할 수 있습니다.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
               // all of these don't work
            Console.WriteLine("{0:C}", 10);
            Console.WriteLine("{0:00.0}", 10);
            Console.WriteLine("{0:0}", 10);
            Console.WriteLine("{0:0.00}", 10);
            Console.WriteLine("{0:0}", 10.0);
            Console.WriteLine("{0:0}", 10.1);
            Console.WriteLine("{0:0.00}", 10.1);

          // works
            Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9));
            Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9.1));
            Console.ReadKey();
        }
    }

    class MyFormatter : IFormatProvider, ICustomFormatter
    {
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            switch (format.ToUpper())
            {
                case "CUSTOM":
                    if (arg is short || arg is int || arg is long)
                        return arg.ToString();
                    if (arg is Single || arg is Double)
                        return String.Format("{0:0.00}",arg);
                    break;
                // Handle other
                default:
                    try
                    {
                        return HandleOtherFormats(format, arg);
                    }
                    catch (FormatException e)
                    {
                        throw new FormatException(String.Format("The format of '{0}' is invalid.", format), e);
                    }
            }
            return arg.ToString(); // only as a last resort
        }

        private string HandleOtherFormats(string format, object arg)
        {
            if (arg is IFormattable)
                return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
            if (arg != null)
                return arg.ToString();
            return String.Empty;
        }

        public object GetFormat(Type formatType)
        {
            if (formatType == typeof(ICustomFormatter))
                return this;
            return null;
        }
    }
}

6

다음은 동일한 메소드 호출을 유지하는 Uwe Keim의 메소드에 대한 대안입니다.

var example1 = MyCustomFormat(123.1);  // Output: 123.10
var example2 = MyCustomFormat(123.95); // Output: 123.95
var example3 = MyCustomFormat(123);    // Output: 123

MyCustomFormat같은되는 :

public static string MyCustomFormat( double myNumber )
{
    var str (string.Format("{0:0.00}", myNumber))
    return (str.EndsWith(".00") ? str.Substring(0, strLastIndexOf(".00")) : str;
}

TrimEnd가 ".00"과 같은 문자열이 아닌 { ',', '.', ''}와 같은 문자 배열을 취하는 것처럼 보이므로 이것은 효과가 없었습니다.- msdn.microsoft.com/en
user1069816

당신 말이 맞아요-내가 어떻게 그리웠는지 모르겠습니다. 제대로 작동하도록 업데이트되었습니다.
Steve

5
현재 스레드의에 따라 CurrentCulture소수 구분 기호가 아닐 수 있습니다 .. CultureInfo.InvariantCulture와 함께 사용 하지 않는 한의 string.Format가치를 확인해야합니다 CultureInfo.NumberFormat.NumberDecimalSeparator.
Groo

6

간단한 한 줄 코드 :

public static string DoFormat(double myNumber)
{
    return string.Format("{0:0.00}", myNumber).Replace(".00","");
}

소수점 구분 기호가 쉼표로 실행되는 경우 문제가 발생합니다. 이 답변에 대한 의견을 확인하십시오 .
앤드류

6

프로그램을 빠르게 실행해야하는 경우 $. {value : formatString} "및 string.Format (formatString, value)에 비해 문자열 형식화 성능이 ~ 35 % 빨라지도록 value.ToString (formatString)을 호출하십시오.

데이터

C # 문자열 형식화 성능-VS2017 15.4.5

암호

using System;
using System.Diagnostics;

public static class StringFormattingPerformance
{
   public static void Main()
   {
      Console.WriteLine("C# String Formatting Performance");
      Console.WriteLine("Milliseconds Per 1 Million Iterations - Best Of 5");
      long stringInterpolationBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return $"{randomDouble:0.##}";
          });
      long stringDotFormatBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return string.Format("{0:0.##}", randomDouble);
          });
      long valueDotToStringBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return randomDouble.ToString("0.##");
          });
      Console.WriteLine(
$@"            $""{{value:formatString}}"": {stringInterpolationBestOf5} ms
 string.Format(formatString, value): {stringDotFormatBestOf5} ms
       value.ToString(formatString): {valueDotToStringBestOf5} ms");
   }

   private static long Measure1MillionIterationsBestOf5(
       Func<double, string> formatDoubleUpToTwoDecimalPlaces)
   {
      long elapsedMillisecondsBestOf5 = long.MaxValue;
      for (int perfRunIndex = 0; perfRunIndex < 5; ++perfRunIndex)
      {
         var random = new Random();
         var stopwatch = Stopwatch.StartNew();
         for (int i = 0; i < 1000000; ++i)
         {
            double randomDouble = random.NextDouble();
            formatDoubleUpToTwoDecimalPlaces(randomDouble);
         }
         stopwatch.Stop();
         elapsedMillisecondsBestOf5 = Math.Min(
            elapsedMillisecondsBestOf5, stopwatch.ElapsedMilliseconds);
      }
      return elapsedMillisecondsBestOf5;
   }
}

코드 출력

C# String Formatting Performance
Milliseconds Per 1 Million Iterations - Best Of 5
            $"{value:formatString}": 419 ms
 string.Format(formatString, value): 419 ms
       value.ToString(formatString): 264 ms

참고 문헌

사용자 지정 숫자 형식 문자열 [docs.microsoft.com]

Qt 차트 BarChart 예 [doc.qt.io]


5

이 작업을 수행 할 기본 제공 형식이없는 것이 걱정됩니다. 값이 정수인지 여부에 따라 다른 형식을 사용해야합니다. 또는 항상 소수점 이하 2 자리로 서식을 지정하고 뒤에 문자열을 조작하여 후행 ".00"을 제거하십시오.


4

다른 답변이 당신에게 도움 이되지 않으면 함수 ContentProperty의 컨트롤을 바인딩하고 있기 때문에 OnLoad이것이 작동하지 않을 수 있습니다.

private void UserControl_Load(object sender, RoutedEventArgs e)
{
  Bind.SetBindingElement(labelName, String.Format("{0:0.00}", PropertyName), Label.ContentProperty) 
}

해결책은 간단합니다. ContentStringFormatxaml에 속성이 있습니다. 따라서 레이블을 만들 때 다음을 수행하십시오.

//if you want the decimal places definite
<Label Content="0" Name="labelName" ContentStringFormat="0.00"/>

또는

//if you want the decimal places to be optional
<Label Content="0" Name="labelName" ContentStringFormat="0.##"/>

3

이런 식으로 작동합니다 :

String.Format("{0:P}", decimal.Parse(Resellers.Fee)).Replace(".00", "")

그 퍼센트를 제공?


2

Kahia가 작성한 코드를 더 명확하게하려면 (명확하지만 텍스트를 추가 할 때 까다로워집니다) ...이 간단한 솔루션을 사용해보십시오.

if (Math.Round((decimal)user.CurrentPoints) == user.CurrentPoints)
     ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0}",user.CurrentPoints);
else
     ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0.0}",user.CurrentPoints);

Math.Round가 두 개의 십진 변수를 비교하도록 여분의 캐스트 (10 진수)를 추가해야했습니다.


1

이것은 나를 위해 일했다!

String amount= "123.0000";
String.Format("{0:0.##}", amount);      // "123.00"

1
작동하지 않습니다. 그는 123.00이 "123"으로 표시되고 123.50이 "123.50"으로 표시되기를 원합니다.
Andrew

1

(T-) SQL 데이터베이스에서 오는 소수를 처리 할 때 nullable 및 nullable이 아닌 소수점을 x 소수점 이하 자릿수로 변환하고 테이블 정의에 대해 코드를 쉽게 검토 할 수 있기를 원합니다. 물론 사용자에게 올바른 소수 자릿수.

불행히도 Entity Framework는 SQL과 같은 것을 자동으로 변환하지 않습니다. decimal(18,2) 소수점 이하 자릿수가 동일한 .NET (사용 가능한 전체 정밀도가있는 소수 만 있기 때문에). 소수점 이하 자릿수를 수동으로 잘라야합니다.

그래서 나는 이렇게했다 :

public static class Extensions
{
    public static string ToStringDecimal(this decimal d, byte decimals)
    {
        var fmt = (decimals>0) ? "0." + new string('0', decimals) : "0";
        return d.ToString(fmt);
    }

    public static string ToStringDecimal(this decimal? d, byte decimals)
    {
        if (!d.HasValue) return "";
        return ToStringDecimal(d.Value, decimals);
    }
}

사용법 예 :

void Main()
{
    decimal d = (decimal)1.2345;
    decimal? d2 = null; 

    Console.WriteLine(d.ToStringDecinal(2)); // prints: "1.23" (2 decimal places)
    Console.WriteLine(d.ToStringDecinal(0)); // prints: "1" (show integer number)
    Console.WriteLine(d2.ToStringDecimal(2)); // prints: "" (show null as empty string)
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.