概要
数値を整形して表示したいことがあります。 例えば、19800 という数値に対して、
-
数字のみ: 19800
-
3ケタごとにコンマ区切り: 19,800
-
指数表記: 1.98e4
など、いろんな表示の仕方があります。
.NET では、ToString メソッドや、string.Format 静的メソッドなどに対して、書式を与えることで、数値の表示の仕方を変えることができます。 また、WPF や Silverlight のデータ バインディングでも、書式設定ができます。
参考:
ToString メソッド
C#では、数値などから文字列への型変換は、そのままではできません。しかし、objectクラスがToStringというメソッドを持っていて、これで文字列化できます。
自作の型を文字列化したい場合は、以下のように、ToStringメソッドをオーバーライドします。
- C#
- VB
- C++
class Point
{
public int X { get; set; }
public int Y { get; set; }
public override string ToString()
{
return "(" + X + ", " + Y + ")";
}
}
Class Point
Public Property X As Integer
Public Property Y As Integer
Public Overrides Function ToString() As String
Return "(" & X & ", " & Y & ")"
End Function
End Class
ref class Point
{
public:
property int X;
property int Y;
virtual String^ ToString() override
{
return "(" + X + ", " + Y + ")";
}
};
以下のように利用できます。
- C#
- VB
- C++
var p = new Point { X = 10, Y = 20 };
Console.WriteLine(p);
Dim p = New Point With {.X = 10, .Y = 20}
Console.WriteLine(p)
auto p = gcnew Point();
p->X = 10;
p->Y = 20;
Console::WriteLine(p);
(10, 20)
書式設定付きの ToString メソッド
intやDateTimeなど、主要な型には、書式設定が可能なバージョンのToStringメソッドが提供されています。書式を、ToStringの引数として渡します。
var n = 1980;
Console.WriteLine(n.ToString("d")); // 1980
Console.WriteLine(n.ToString("x")); // 7bc
var x = 0.12;
Console.WriteLine(x.ToString("f")); // 0.12
Console.WriteLine(x.ToString("e")); // 1.200000e-001
"d"
などが書式です。
書式の書き方については後程改めて説明します。
複合書式(string.Format)
stringクラスのFormat静的メソッドで、複数の値をまとめて書式設定することができます。
var x = 7;
var y = 13;
var line = string.Format("{0} × {1} = {2}", x, y, x * y);
Console.WriteLine(line); // 7 × 13 = 91
1つ目の引数が書式で、2つ目以降の引数を、それぞれ、{0}
、{1}
、{2}
の部分に展開します。
{}
内の数字は、何番目の引数を参照するかのインデックス(0 始まり)を表します。
Console.Writeや、StreamWriter.Writeなど、内部的にstring.Formatを呼び出してくれる(=文字列整形の挙動は string.Format と同じ)ものもあります。
Console.WriteLine("({0}, {1})", 1, 2); // (1, 2)
インデックスに続けて、,
(コンマ)で区切って幅を指定することもできます。この時、正の数を指定すると右詰め、負の数を指定すると左詰めになります。
Console.WriteLine("({0,-5}) ({1,5})", 1, 1); // (1 ) ( 1)
また、インデックスに続けて、:
(コロン)で区切って、個別の書式(= ToString メソッドに渡す書式)を指定できます。
Console.WriteLine("{0:x}, {1:c}", 123, 123); // 7b, \123
//↑ "{0}, {1}", 123.ToString("x"), 123.ToString("c") と同じ扱い
それでは、個別の書式についてみていきましょう。
数値書式(標準)
整数
dは10進数、xは16進数を表します。xを大文字にするか小文字にするかで、16進数のa~fの大小を選べます。
// d:10進数、0詰め桁数指定
Console.WriteLine("{0:d}, {0:d4}", 5); // 5, 0005
// x: 16進数、0詰め桁数指定
Console.WriteLine("{0:x}, {0:X}, {0:x4}, {0:X4}", 140); // 8c, 8C, 008c, 008C
浮動小数点数
fで固定小数点表示、eで指数表記を表します。また、gで、fとeのどちらか、簡潔な方を自動選択してくれます。
// f: 小数点、小数点以下の桁数指定
Console.WriteLine("{0:f}, {0:f5}", 0.1234); // 0.12, 0.12340
// e: 指数表記、精度指定
Console.WriteLine("{0:e}, {0:e2}, {0:E2}", 0.1234); // 1.234000e-001, 1.23e-001, 1.23E-001
// g: f か e かを自動選択
Console.WriteLine("{0:g}, {1:g}", 1200000000000000.0, 0.12); // 1.2e+15, 0.12
その他
適宜桁区切り、通貨記号などをはさんでくれるn、cや、精度を自動判定してくれるr、パーセント化してくれるpなども利用できます。
// n: 適宜、桁区切りなどを挿入、小数点以下の桁数指定
Console.WriteLine("{0:n}, {0:n0}", 1234567); // 1,234,567.00, 1,234,567
// c: 通貨
Console.WriteLine("{0:c}", 1234567); // \1,234,567
// r: 復元するのに十分な桁数で出力
Console.WriteLine("{0:r}", 0.1234567890123456789f); // 0.123456791
// p: パーセント表示、小数点以下の桁数指定
Console.WriteLine("{0:p1}", 0.1234); // 12.30%
- 参考:標準の数値書式指定文字列
数値書式(カスタム)
数値は、0や#(ナンバー記号)などを使って、かなり自由な書式を作れます。
// 桁数を明示。0. の 0 は省略
Console.WriteLine("{0:#.##}", 0.2345); // .23
// 0詰め4ケタ.4ケタ
Console.WriteLine("{0:0000.0000}", 1.23); // 0001.2300
// 3ケタ区切り、小数点以下0詰め2ケタ
Console.WriteLine("{0:#,#.00}", 1234567); // 1,234,567.00
日付の書式
DateTime 型、DateTimeOffset 型に対しても、標準書式("d"
など)や、カスタム書式("y/M/d"
など)を設定できます。
var d = new DateTime(2008, 5, 4, 8, 30, 0);
Console.WriteLine(d.ToString("d")); // 2008/05/04
Console.WriteLine(d.ToString("D")); // 2008年5月4日
var d = new DateTime(2008, 5, 4, 8, 30, 0);
Console.WriteLine(d.ToString("y/M/d h:m:s")); // 8/5/4 8:30:0
Console.WriteLine(d.ToString("hh:mm:ss")); // 08:30:00
Console.WriteLine(d.ToString("yy/MM/dd")); // 08/05/04 8:30:0
Console.WriteLine(d.ToString("yyyy/MM/dd")); // 2008/12/04
Console.WriteLine(d.ToString("ddd dddd")); // 日 日曜日
カスタム書式で、 /
や :
などの記号は自由な位置に挿入できます。
その他、以下の文字は特別な意味を持ちます。
記号 | 意味 |
---|---|
y, yy, yyyy | 年。それぞれ、下2桁(2桁目が0なら1ケタ)、下2桁(2桁目は0詰め)、4ケタ表示。 |
M, MM | 月。2文字並べた場合、0を挿入して2ケタにする(以下の、dd などでも同様)。 |
d, dd | 日。 |
h, hh | 時(12時間形式)。 |
H, HH | 時(24時間形式)。 |
m, mm | 分。 |
s, ss | 秒。 |
f | 秒の小数点以下。欲しい桁数分、f を並べる。 |
ddd, dddd | 曜日。ddd が省略名(mon とか 月 とか)、dddd が完全名(Monday とか 月曜日 とか)。 |
MMM, MMMM | 月名。MMM が省略名(Jun とか 1 とか)、MMMM が完全名(Junuary とか 5月 とか)。 |
t, tt | AM か PM か。日本語カルチャーで t (省略名)を使うと残念なことに(午前でも午後でも「午」と表示)。 |
g | 年号。 |
K | タイム ゾーン。 |
書式とカルチャー
注意点として、文字列の書式設定の結果は、カルチャーに依存します。
例えば、金額表示(通貨書式 "c"
を使う)を考えてみましょう。
世界各国の通販サイトでも覗いていただけるとわかるんですが、以下のような部分が、国によってすべて異なります。
-
小数点以下の有無
-
小数点に使う記号
-
3ケタずつの区切りに使う記号
-
通貨記号
-
負の数の表し方
"c"
書式を使うと、金額に対して、カルチャーごとに最適な整形を掛けてくれます。
using System;
using System.Globalization;
class Program
{
static void Main()
{
var cultures = new[] { "ja-jp", "zh-cn", "en-us", "en-gb", "fr-fr", "de-de", "pt-br", "tr-tr", "he-il" };
var price = 9800;
foreach (var c in cultures)
{
var culture = new CultureInfo(c);
var plus = price.ToString("c", culture);
var minus = (-price).ToString("c", culture);
Console.WriteLine("{0,-11} / {1,-12} ({2})", plus, minus, culture.DisplayName);
}
}
}
¥9,800 / -¥9,800 (日本語 (日本)) ¥9,800.00 / ¥-9,800.00 (中国語 (中華人民共和国)) $9,800.00 / ($9,800.00) (英語 (米国)) £9,800.00 / -£9,800.00 (英語 (英国)) 9 800,00 € / -9 800,00 € (フランス語 (フランス)) 9.800,00 € / -9.800,00 € (ドイツ語 (ドイツ)) R$ 9.800,00 / -R$ 9.800,00 (ポルトガル語 (ブラジル)) 9.800,00 TL / -9.800,00 TL (トルコ語 (トルコ)) ₪ 9,800.00 / ₪-9,800.00 (ヘブライ語 (イスラエル))
ちなみに、特にカルチャーを指定しなかった場合、OS 設定のカルチャー(日本語 Windows を使っているなら、デフォルトでは当然日本語)に基づいて整形します。
通貨に限らず、小数点や区切り文字、日付の書式などは文化の影響を受けます。