文字列形式を使用して2桁までの小数または単純な整数を表示する


291

表示する価格フィールドがあり、100または100.99または100.9のいずれかになる場合があります。たとえば、価格に小数が入力されている場合にのみ、小数点以下2桁で価格を表示します。 100.00ではなく100を表示し、価格が100.2の場合、100.22も同様に100.20を表示する必要があります。私はググっていくつかの例に出くわしましたが、それらは私が望んでいたものと正確には一致しませんでした:

// 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 2013

2
@BinaryWorrierこの質問は重複している可能性があると思いますが、はるかによく、より完全な答えがあります。IMO他の1つは、この1つの複製としてマークする必要があります。
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 2013

18
@ BrainSlugs83:現在のスレッドのによってはCurrentCulture、小数点記号がにならない場合があります.CultureInfo.InvariantCultureで使用しない限りstring.Format、の値を確認する必要がありCultureInfo.NumberFormat.NumberDecimalSeparator、それが実際のPITAになります。:)
Groo

@Uweケイム私が持っている場合はどのような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(こちら)からのものです。だから私は個人的に次のようなものを使います:

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

20
最初は、元の質問を何度も読み直すまで、これが答えになるはずだと思いました。OPは彼が正確に何を望んでいるのか完全に明確ではありませんが、誰かが分数を入力した場合、彼は常に小数点以下2桁を望んでいるようです。したがって、誰かが1.1を入力した場合、1.10が必要になります。このコードはそれをしません。
Doug S

40
おっと、もう一度読んで、あなたは正しい。だから、これは正しい答えではありませんが、少なくとも誰かがこれが役に立つと思うかもしれません。
Gh61、2014年

これにより、必要なOPを実現できます。stackoverflow.com
Andrew

私はそれが便利で、GridViewのBoundFieldがSqlDoubleで何を実行するかをフォーマットの指示なしで(ある程度)一致させたところです。表示する最大数を指定する必要があります。(対BoundField、好きなだけ表示したり、表示したりできます)
fortboise 16/12/30

うん、これは便利でしたが、小数が存在する場合に小数点以下2桁を表示する方法は?つまり、整数の場合、小数を表示しませんか?
Nigel Fds 2017年

64

これは、一般的なフォーマット浮動小数点の使用例です。

残念ながら、組み込みの1文字形式の文字列(F、G、Nなど)では、これを直接行うことはできません。
たとえば、num.ToString("F2")は常にのように小数点以下2桁を表示し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((number%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-us/を参照してくださいlibrary / system.string.trimend.aspx
user1069816

あなたが正しい-私がどのようにそれを逃したのかわからない。正しく機能するように更新しました。
Steve

5
現在のスレッドのによってはCurrentCulture、小数点記号がにならない場合があります.CultureInfo.InvariantCultureで使用しない限りstring.Format、の値を確認する必要がありますCultureInfo.NumberFormat.NumberDecimalSeparator。これはかなり洗練されていません。
Groo

6

単純な1行のコード:

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

この問題は、小数点記号がカンマである場合に実行されます。この回答のコメントを確認してください。
Andrew

6

プログラムを迅速に実行する必要がある場合は、value.ToString(formatString)を呼び出して、$ "{value:formatString}"およびstring.Format(formatString、value)に比べて〜35%高速な文字列フォーマットパフォーマンスを実現します。

データ

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

解決策は簡単ですContentStringFormat。xamlにプロパティがあります。ラベルを作成するときは、次のようにします。

//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", "")

それはパーセントを与えますか?

3

試してください:

String.Format("{0:0.00}", Convert.ToDecimal(totalPrice));

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で2つの10進数変数を比較するには、余分なキャスト(10進数)を追加する必要がありました。



1

(T-)SQLデータベースからの10進数を扱う場合、null可能およびnull不可の10進数を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.