C#数値型の選び方完全ガイド|int・long・float・double・decimalの違いと使い分け

はじめに

C#で数値を扱うとき、最初に迷いやすいのが「どの数値型を使えばよいのか」です。整数ならintlong、小数ならfloatdouble、金額ならdecimalなど、C#には用途に応じた複数の数値型があります。

結論から言うと、基本方針はシンプルです。通常の整数はint、大きな整数はlong、一般的な小数計算はdouble、金額や正確な10進数計算はdecimalを使います。floatはメモリ使用量を抑えたい場面や、ゲーム・画像処理・機械学習などで使われることがあります。

この記事では、C#数値型の全体像から、intlongfloatdoubledecimalの違い、型変換、リテラル、よくある落とし穴、実務での設計ポイントまで、初心者にもわかりやすく解説します。

1. C#の数値型とは?まず押さえる全体像

C#の数値型とは、整数や小数などの数値データを扱うための型です。変数に数値を入れるとき、C#ではその値がどの種類の数値なのかを型として明確に指定します。

C#
int count = 10;
double rate = 0.15;
decimal price = 1980m;

このように、同じ「数値」でも、件数を表すのか、小数を含む割合を表すのか、金額を表すのかによって適した型は変わります。

C#は静的型付け言語なので、変数・定数・式には型があり、コンパイラが型の整合性をチェックします。たとえば、int同士は加算できますが、intboolをそのまま加算するような処理はできません。

1-1. C#の数値型は「整数型」「浮動小数点型」「decimal型」に分けて考える

C#の数値型は、大きく次の3つに分けて考えると理解しやすくなります。

分類主な型用途
整数型intlongshortbyte件数、年齢、回数、IDなど
浮動小数点型floatdouble測定値、統計、座標、科学計算など
10進数型decimal金額、税率、会計処理など

整数型は小数点を含まない値を扱います。10-51000000のような値です。

浮動小数点型は小数を扱います。3.140.1-12.5のような値です。ただし、floatdoubleは2進数ベースで小数を表すため、10進数の小数を常に正確に表せるわけではありません。

decimalも小数を扱う型ですが、特に10進数の精度が重要な計算に向いています。MicrosoftのC#リファレンスでも、decimalは金融アプリケーション、通貨額、利率など、小数点以下の桁数によって精度が決まる数値に適していると説明されています。

1-2. よく使う数値型はint・long・float・double・decimal

C#には多くの数値型がありますが、実務や学習で特によく使うのは次の5つです。

読み方主な用途
intイント一般的な整数
longロング大きな整数
floatフロートメモリを抑えたい小数
doubleダブル一般的な小数
decimalデシマル金額など正確な10進数

初心者は、まずこの5つの使い分けを覚えれば十分です。shortbyteuintulongなどもありますが、最初から細かく使い分けようとすると、かえってコードが読みにくくなることがあります。

1-3. 数値型を間違えると起きる問題:桁あふれ・誤差・性能低下

C#数値型の選び方を間違えると、次のような問題が起きます。

1つ目は、桁あふれです。たとえばintの最大値を超える大きな数値を扱おうとすると、オーバーフローが発生する可能性があります。intは符号付き32ビット整数で、範囲は-2,147,483,648から2,147,483,647までです。これを超える可能性があるならlongを検討します。

2つ目は、計算誤差です。doublefloat0.1のような10進小数を扱うと、内部表現の都合で誤差が発生することがあります。金額計算でこの誤差が積み重なると、請求金額や税額がずれる原因になります。

3つ目は、性能低下やメモリ使用量の増加です。必要以上に大きな型を大量データに使うと、メモリを余分に消費することがあります。一方で、金額計算で速度だけを重視してdoubleを使うと、精度面で問題が出ることがあります。

1-4. C#の数値型はすべて値型であることを理解する

C#の組み込み数値型は値型です。整数数値型はすべて値型であり、浮動小数点数値型もすべて値型です。

値型とは、基本的に値そのものを保持する型です。たとえば次のコードでは、baの値がコピーされます。

C#
int a = 10;
int b = a;

b = 20;

Console.WriteLine(a); // 10
Console.WriteLine(b); // 20

bを変更してもaは変わりません。数値型を扱ううえでは、この「値がコピーされる」という感覚を持っておくと理解しやすくなります。

2. 【結論】C#数値型の選び方早見表

C#数値型の選び方で迷ったら、まずは次の方針で考えましょう。

扱いたい値基本的に選ぶ型
一般的な整数int
intに収まらない大きな整数long
一般的な小数double
メモリを抑えたい小数float
金額・税率・会計処理decimal

MicrosoftのC#ドキュメントでも、一般的な浮動小数点計算にはdouble、メモリ制約がある場合にはfloat、正確な10進数精度が必要な場合にはdecimalを使うという方針が示されています。

2-1. 迷ったら整数はint、小数はdouble、金額はdecimalが基本

初心者が最初に覚えるべき基本ルールは、次の3つです。

整数ならintを使います。

C#
int age = 30;
int count = 100;
int retryCount = 3;

小数ならdoubleを使います。

C#
double average = 72.5;
double distance = 123.45;
double rate = 0.08;

金額ならdecimalを使います。

C#
decimal price = 1980m;
decimal taxRate = 0.10m;
decimal total = price * (1 + taxRate);

この3つを押さえておけば、C#数値型の選択で大きく失敗することは少なくなります。

2-2. 用途別おすすめ数値型一覧

用途おすすめ型理由
年齢int小数不要で範囲も十分
件数int通常の件数なら十分
ループカウンタintC#で標準的に使われる
商品IDlongまたはstring大きなIDや外部連携では注意
ファイルサイズlong大きな値になりやすい
座標floatまたはdouble用途により精度とメモリで選ぶ
平均値double一般的な小数計算に向く
統計計算double精度と性能のバランスがよい
金額decimal10進数の正確性が重要
税率decimal金額計算と組み合わせるため
DBのBIGINTlongSQL ServerなどのBIGINTに対応しやすい
DBのDECIMALdecimal固定小数点の値に対応しやすい

実務では、単に「数字だからint」と考えるのではなく、「その値は何を表すのか」「最大値はどれくらいか」「小数誤差が許されるか」を考えることが重要です。

2-3. 範囲・精度・メモリサイズの比較表

代表的なC#数値型の範囲、精度、サイズは次のとおりです。

分類範囲・精度の目安サイズ
byte整数0〜2551バイト
short整数-32,768〜32,7672バイト
int整数-2,147,483,648〜2,147,483,6474バイト
long整数-9,223,372,036,854,775,808〜9,223,372,036,854,775,8078バイト
float小数約6〜9桁の精度4バイト
double小数約15〜17桁の精度8バイト
decimal10進小数28〜29桁の精度16バイト

整数型の範囲はC#リファレンスで定義されており、intは32ビット、longは64ビットの符号付き整数です。 また、floatdoubledecimalはそれぞれ4バイト、8バイト、16バイトで、精度も異なります。

2-4. 初心者が最初に覚えるべき判断基準

初心者は、次の順番で判断するとわかりやすいです。

まず、小数が必要かどうかを考えます。小数が不要なら整数型です。通常はintで十分ですが、21億を超える可能性があるならlongを使います。

次に、小数が必要な場合、その値が金額かどうかを考えます。金額、税率、利率、会計処理など、10進数としての正確さが重要ならdecimalを使います。

金額ではなく、測定値、平均値、割合、科学計算などであれば、基本はdoubleです。大量データやゲーム開発などでメモリ使用量を抑えたい場合はfloatを検討します。

3. 整数を扱うC#数値型:int・long・short・byteの違い

整数型は、小数点を含まない数値を扱う型です。C#では、intlongshortbyteなどの整数型が用意されています。

代表的な整数型は次のとおりです。

範囲サイズ主な用途
byte0〜2551バイトバイナリデータ、RGB値など
short-32,768〜32,7672バイト小さな整数、外部仕様に合わせる場合
int約±21億4バイト一般的な整数
long約±922京8バイト大きな整数

C#では、整数型ごとに範囲とサイズが決まっています。byteは符号なし8ビット、shortは符号付き16ビット、intは符号付き32ビット、longは符号付き64ビットです。

3-1. int型とは:C#で最もよく使う整数型

intは、C#で最もよく使われる整数型です。件数、年齢、回数、インデックス、フラグ以外の小さな数値など、多くの場面で使います。

C#
int age = 25;
int score = 80;
int count = 100;
int index = 0;

intの範囲は-2,147,483,648から2,147,483,647までです。通常の業務アプリケーションで扱う年齢、数量、回数、ページ番号などであれば、ほとんどの場合intで十分です。

ただし、ユーザー数、ログ件数、アクセス数、累計処理件数など、将来的に21億を超える可能性がある値には注意が必要です。そのような場合はlongを検討します。

3-2. long型とは:intに収まらない大きな整数を扱う型

longは、intよりも大きな整数を扱うための型です。

C#
long totalAccessCount = 5_000_000_000L;
long fileSize = 10_737_418_240L;
long userId = 9_000_000_000L;

longの範囲は-9,223,372,036,854,775,808から9,223,372,036,854,775,807までです。intよりもはるかに大きな値を扱えます。

longを使う代表的な場面は、次のようなケースです。

  • 大きなID

  • ファイルサイズ

  • 累計アクセス数

  • 大量データの件数

  • Unix時間などの時刻表現

  • データベースのBIGINTに対応する値

longのリテラルには、見やすさのために大文字のLを付けるのが一般的です。

C#
long value = 3000000000L;

小文字のlも使えますが、数字の1と紛らわしいため、大文字のLを使うほうが読みやすくなります。

3-3. short・byte型とは:メモリやデータサイズを意識する場面で使う型

shortは16ビットの整数型で、範囲は-32,768から32,767までです。byteは8ビットの整数型で、範囲は0から255までです。

C#
short temperature = -10;
byte red = 255;
byte green = 128;
byte blue = 0;

byteは、画像のRGB値、バイナリデータ、通信データ、ファイルデータなどでよく使われます。たとえばRGBの各色は0〜255で表されることが多いため、byteと相性がよいです。

一方、shortは日常的な業務コードではそれほど頻繁には使いません。メモリを節約したい、大量の数値配列を扱う、外部ファイル形式や通信仕様で16ビット整数が指定されている、といった場面で使います。

ただし、むやみにshortbyteを使うと、演算時にintへ変換されることもあり、コードがかえって複雑になる場合があります。可読性を重視するなら、通常の整数にはintを使うのが無難です。

3-4. 符号あり・符号なしの違い:intとuint、longとulong

C#の整数型には、符号ありと符号なしがあります。

符号あり符号なし説明
sbytebyte8ビット整数
shortushort16ビット整数
intuint32ビット整数
longulong64ビット整数

符号ありは、正の数・負の数・0を扱えます。符号なしは、0以上の値だけを扱います。その代わり、同じビット数で表せる正の範囲が広くなります。

たとえば、int-2,147,483,648から2,147,483,647までですが、uint0から4,294,967,295までです。longは負の値も扱えますが、ulong0から18,446,744,073,709,551,615まで扱えます。

C#
uint positiveCount = 4_000_000_000U;
ulong hugeValue = 18_000_000_000_000_000_000UL;

ただし、実務では「負の値を取らないから必ずuintにする」とは限りません。多くの.NET APIではintlongが標準的に使われるため、符号なし型を使うと型変換が増えて扱いにくくなる場合があります。

3-5. 整数型を選ぶときの注意点:オーバーフローと最大値・最小値

整数型には最大値と最小値があります。範囲を超える計算をすると、オーバーフローが発生します。

C#
int max = int.MaxValue;
Console.WriteLine(max); // 2147483647

オーバーフローを避けるには、仕様上の最大値を確認し、必要であればより大きな型を使います。

C#
long largeCount = 3_000_000_000L;

また、型ごとの最大値・最小値はMaxValueMinValueで確認できます。

C#
Console.WriteLine(int.MinValue);
Console.WriteLine(int.MaxValue);
Console.WriteLine(long.MinValue);
Console.WriteLine(long.MaxValue);

C#の整数型には、それぞれMinValueMaxValueが用意されています。ネイティブサイズのnintnuintを除き、これらはコンパイル時定数です。

4. 小数を扱うC#数値型:float・double・decimalの違い

C#で小数を扱う主な型は、floatdoubledecimalです。

サイズ精度主な用途
float4バイト約6〜9桁ゲーム、画像処理、大量データ
double8バイト約15〜17桁一般的な小数計算、統計、科学計算
decimal16バイト28〜29桁金額、税率、会計処理

floatdoubleは2進浮動小数点型です。一方、decimalは10進数の精度が必要な場面に向いた型です。C#リファレンスでは、floatは4バイト、doubleは8バイト、decimalは16バイトとされています。

4-1. float型とは:メモリを抑えたい小数計算向け

floatは、32ビットの単精度浮動小数点型です。doubleよりもメモリ使用量が少ない一方で、精度は低くなります。

C#
float x = 1.5f;
float y = 3.14f;

floatリテラルにはfまたはFサフィックスを付けます。付けない場合、小数リテラルは基本的にdoubleとして扱われるため、float変数に代入するとコンパイルエラーになることがあります。

C#
float value1 = 1.23f; // OK
// float value2 = 1.23; // コンパイルエラー

floatが向いているのは、次のような場面です。

  • ゲーム開発の座標

  • 3Dグラフィックス

  • 画像処理

  • 音声処理

  • 大量の小数データ

  • 機械学習など、メモリ効率が重要な処理

ただし、一般的な業務アプリケーションで小数を扱う場合は、まずdoubleを検討するほうが無難です。

4-2. double型とは:一般的な小数計算で標準的に使う型

doubleは、C#で一般的な小数計算に広く使われる型です。64ビットの倍精度浮動小数点型で、floatより高い精度を持ちます。

C#
double pi = 3.141592653589793;
double average = 82.35;
double distance = 12345.6789;

小数リテラルにサフィックスを付けない場合、C#ではdoubleとして扱われます。

C#
var value = 1.23; // double

doubleが向いているのは、次のような場面です。

  • 平均値

  • 割合

  • 測定値

  • 科学計算

  • 統計処理

  • 一般的な小数計算

金額計算でなければ、小数にはまずdoubleを使うと考えて問題ありません。

4-3. decimal型とは:金額や正確な10進数計算に向く型

decimalは、10進数としての正確さが重要な場面に向いた型です。特に、金額、税率、利率、会計処理などで使います。

C#
decimal price = 1980m;
decimal taxRate = 0.10m;
decimal tax = price * taxRate;
decimal total = price + tax;

decimalリテラルにはmまたはMサフィックスを付けます。

C#
decimal amount = 123.45m;

decimalfloatdoubleよりサイズが大きく、計算性能面では不利になることがあります。しかし、10進数の精度が重要な金額計算では、正確性を優先してdecimalを使うのが基本です。

4-4. float・doubleで誤差が発生する理由

floatdoubleで誤差が発生する理由は、内部的に2進数で小数を表現しているためです。

たとえば、10進数の0.1は人間にとっては簡単な小数ですが、2進数では正確に表現できません。そのため、double0.1を加算すると、期待した結果とわずかに異なる値になることがあります。

C#
double a = 0.1;
double b = 0.2;
double c = a + b;

Console.WriteLine(c); // 0.30000000000000004 など

これはC#特有のバグではなく、浮動小数点数の性質です。floatdoubleを使う場合は、「小数の計算結果には微小な誤差が含まれる可能性がある」と理解しておく必要があります。

MicrosoftのC#リファレンスでも、0.1decimalでは正確に表せる一方、doublefloatでは正確に表せず、10進データにdoublefloatを使うと予期しない丸めエラーが発生する可能性があると説明されています。

4-5. decimalが正確な計算に向く理由とデメリット

decimalは、10進数の精度が必要な値に向いています。金額のように「1円単位」「小数第2位まで」「税率10%」といった10進数ベースのルールで扱う値には、decimalが適しています。

C#
decimal a = 0.1m;
decimal b = 0.2m;
decimal c = a + b;

Console.WriteLine(c); // 0.3

ただし、decimalにもデメリットがあります。

まず、サイズが16バイトと大きく、doubleの8バイト、floatの4バイトよりメモリを使います。次に、浮動小数点演算に比べて計算が遅くなる場合があります。大量の数値を高速に処理する科学計算やゲーム処理では、doublefloatのほうが適していることがあります。

つまり、decimalは「常に最強の小数型」ではありません。金額や会計など、10進数の正確性が必要な場面で使う型です。

5. int・long・float・double・decimalの具体的な使い分け

ここからは、実務で特によく使うintlongfloatdoubledecimalの使い分けを具体例で見ていきます。

5-1. 件数・年齢・回数などの整数にはintを使う

件数、年齢、回数、点数、ページ番号、配列のインデックスなど、小数を必要としない一般的な値にはintを使います。

C#
int age = 28;
int itemCount = 15;
int retryCount = 3;
int pageNumber = 1;

intはC#で最も標準的な整数型です。可読性が高く、多くのAPIやサンプルコードでも使われています。

たとえば、次のような値はintで十分です。

C#
int userAge = 35;
int quantity = 5;
int score = 90;
int maxRetryCount = 3;

一方で、intに収まるか不安な値、将来的に非常に大きくなる値はlongを検討します。

5-2. ID・ファイルサイズ・大きな件数にはlongを使う

longは、大きな整数を扱うときに使います。

C#
long fileSize = 5_368_709_120L;
long totalViewCount = 10_000_000_000L;
long orderId = 9_876_543_210L;

特に、次のような値はlongにすることが多いです。

  • ファイルサイズ

  • 累計ログ件数

  • 大規模サービスのユーザー数

  • データベースのBIGINT

  • 外部APIから返る大きなID

  • ミリ秒単位のタイムスタンプ

IDについては注意が必要です。数値として計算しないIDであれば、longではなくstringで扱うほうが安全な場合もあります。たとえば、先頭に0が付く可能性があるIDや、桁数が非常に大きい外部サービスのIDは、文字列として扱うことを検討します。

5-3. 座標・ゲーム・画像処理ではfloatを検討する

floatは、精度よりもメモリ効率や処理量が重要な場面で検討します。

C#
float x = 10.5f;
float y = 20.25f;
float speed = 3.5f;

ゲーム開発や3Dグラフィックスでは、座標、速度、回転角度などで大量の小数を扱います。このような場面では、doubleよりもサイズが小さいfloatが選ばれることがあります。

C#
struct Position
{
public float X;
public float Y;
public float Z;
}

ただし、floatdoubleより精度が低いため、精度が重要な計算では不向きです。業務システムの割合計算や統計処理では、基本的にdoubleを使うほうが扱いやすいです。

5-4. 科学計算・統計・一般的な小数計算にはdoubleを使う

doubleは、C#における一般的な小数計算の標準的な選択肢です。

C#
double height = 170.5;
double weight = 65.2;
double bmi = weight / Math.Pow(height / 100, 2);

平均値、標準偏差、距離、速度、確率、統計値など、金額以外の小数計算ではdoubleを使うことが多いです。

C#
double total = 0;
double[] scores = { 80.5, 90.0, 76.5 };

foreach (double score in scores)
{
total += score;
}

double average = total / scores.Length;

doubleは精度と性能のバランスがよく、数学関数を提供するMathクラスの多くのメソッドもdoubleを中心に使います。

5-5. 金額・税率・会計処理にはdecimalを使う

金額計算では、doubleではなくdecimalを使います。

C#
decimal price = 1000m;
decimal taxRate = 0.10m;
decimal tax = price * taxRate;
decimal total = price + tax;

Console.WriteLine(total); // 1100.00 など

金額計算では、1円、1セント、小数第2位など、10進数としての正確さが重要です。doubleの微小な誤差が積み重なると、最終的な請求金額や会計処理に影響する可能性があります。

C#
decimal unitPrice = 19.99m;
int quantity = 3;
decimal subtotal = unitPrice * quantity;

decimalを使うときは、リテラルにmを付けることを忘れないようにします。

C#
decimal amount = 100.0m;

5-6. データベースやAPI連携で型を選ぶときの考え方

データベースやAPIと連携する場合は、C#側だけでなく、相手側の型にも合わせる必要があります。

たとえば、データベースの整数型がINTならC#ではintBIGINTならlongを使うことが多いです。金額や固定小数点の値がDECIMALNUMERICで定義されているなら、C#ではdecimalを使うのが自然です。

API連携では、JSONの数値がどの範囲になるか、IDが数値なのか文字列なのかを確認します。JavaScript環境では大きな整数の扱いに注意が必要なため、外部APIのIDは文字列として返されることもあります。

型を選ぶときは、次の点を確認しましょう。

  • 相手側の型は何か

  • 最大値・最小値はどれくらいか

  • 小数点以下の桁数は固定か

  • 金額や税率のように正確性が必要か

  • IDは計算対象か、それとも識別子にすぎないか

6. C#数値型のリテラルとサフィックス

リテラルとは、コードに直接書く値のことです。

C#
int count = 10;        // 10 が整数リテラル
double rate = 0.1; // 0.1 が実数リテラル
decimal price = 100m; // 100m がdecimalリテラル

C#では、数値リテラルにサフィックスを付けることで、型を明示できます。

6-1. 整数リテラルの基本

整数リテラルは、通常はそのまま数値を書きます。

C#
int a = 42;
int b = 1000;

C#の整数リテラルには、10進数、16進数、2進数があります。10進数はプレフィックスなし、16進数は0xまたは0X、2進数は0bまたは0Bを使います。

C#
var decimalLiteral = 42;
var hexLiteral = 0x2A;
var binaryLiteral = 0b_0010_1010;

また、桁区切りとして_を使うこともできます。

C#
int million = 1_000_000;
long large = 9_000_000_000L;

_を使うと、大きな数値が読みやすくなります。

6-2. long型を明示するLサフィックス

long型のリテラルには、Lサフィックスを付けます。

C#
long value = 3_000_000_000L;

サフィックスなしの整数リテラルは、値を表現できる最初の型としてintuintlongulongの順に扱われます。Lまたはlを付けると、longまたはulongとして扱われます。

小文字のlも使えますが、数字の1と紛らわしいため、実務では大文字のLを使うのがおすすめです。

C#
long good = 10000000000L;
// long hardToRead = 10000000000l; // 1と紛らわしい

6-3. float型を明示するfサフィックス

float型のリテラルには、fまたはFサフィックスを付けます。

C#
float speed = 12.5f;
float rate = 0.75F;

サフィックスを付けない小数リテラルはdoubleとして扱われます。そのため、次のコードはコンパイルエラーになります。

C#
// float value = 1.23; // doubleをfloatに暗黙変換できない
float value = 1.23f;

実数リテラルでは、サフィックスなし、またはdD付きはdoublefF付きはfloatmM付きはdecimalです。

6-4. decimal型を明示するmサフィックス

decimal型のリテラルには、mまたはMサフィックスを付けます。

C#
decimal price = 1980m;
decimal taxRate = 0.10m;
decimal discount = 0.05M;

mはmoneyのmと覚えるとわかりやすいです。正式にはdecimalリテラルを表すサフィックスですが、金額計算でよく使うため、実務でも頻繁に見かけます。

次のように、mを付け忘れるとコンパイルエラーになります。

C#
// decimal price = 19.99; // doubleをdecimalに暗黙変換できない
decimal price = 19.99m;

6-5. サフィックスを付け忘れたときに起きるコンパイルエラー

サフィックスを付け忘れると、意図した型ではなくdoubleintとして解釈され、コンパイルエラーになることがあります。

C#
// float x = 1.5;      // エラー
float x = 1.5f;

// decimal y = 1.5; // エラー
decimal y = 1.5m;

整数でも、範囲に収まらない値を小さい型に代入しようとするとエラーになります。

C#
byte a = 17;
// byte b = 300; // エラー:byteの範囲外

C#では、整数リテラルの値が変換先の型の範囲内にない場合、コンパイルエラーになります。

7. C#数値型の型変換とキャスト

C#では、異なる数値型の間で変換が必要になることがあります。型変換には、暗黙的な型変換と明示的な型変換があります。

7-1. 暗黙的な型変換と明示的な型変換の違い

暗黙的な型変換とは、キャストを書かなくても自動で変換される変換です。基本的に、変換しても情報が失われにくい場合に許可されます。

C#
int a = 100;
long b = a; // intからlongへ暗黙変換

明示的な型変換とは、キャストを書いて変換する方法です。情報が失われる可能性がある場合に必要です。

C#
double x = 123.45;
int y = (int)x; // 小数部分が失われる

整数数値型では、変換先の型が変換元のすべての値を格納できる場合は暗黙変換できます。そうでない場合は、キャストによる明示的な変換が必要です。

7-2. intからlong、floatからdoubleへの変換

intからlongへの変換は、値の範囲が広がるため暗黙的に行えます。

C#
int count = 100;
long total = count;

floatからdoubleへの変換も暗黙的に行えます。

C#
float f = 1.23f;
double d = f;

C#の浮動小数点数値型の間で暗黙的に変換できるのは、floatからdoubleへの変換だけです。その他の浮動小数点型同士の変換には明示的なキャストが必要です。

7-3. doubleからint、decimalからintに変換するときの注意点

doubleからintdecimalからintに変換すると、小数部分が失われます。

C#
double d = 123.99;
int i = (int)d;

Console.WriteLine(i); // 123

この変換では、四捨五入ではなく0方向への丸め、つまり小数部分の切り捨てに近い動作になります。

C#
decimal m = 123.99m;
int n = (int)m;

Console.WriteLine(n); // 123

C#の組み込み数値変換では、decimalを整数型へ変換すると0方向に丸められ、結果が変換先の範囲外であればOverflowExceptionがスローされます。doublefloatを整数型へ変換する場合も0方向に丸められますが、範囲外の場合の動作はオーバーフローチェックの文脈に依存します。

7-4. Convert・Parse・TryParseの使い分け

文字列から数値に変換する場合は、ParseTryParseConvertを使います。

Parseは、変換できない文字列が来ると例外を投げます。

C#
string text = "123";
int value = int.Parse(text);

TryParseは、変換に成功したかどうかをboolで返します。ユーザー入力や外部データのように、正しい数値とは限らない値を扱う場合に向いています。

C#
string input = "123";

if (int.TryParse(input, out int result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("数値に変換できません");
}

Convertは、さまざまな型から数値型へ変換できます。

C#
string text = "123";
int value = Convert.ToInt32(text);

実務では、ユーザー入力やCSV、APIレスポンスなど、失敗する可能性がある変換にはTryParseを使うのが安全です。

7-5. 小数から整数へ変換するときの丸め・切り捨て

小数から整数へ変換するときは、目的に応じて方法を選ぶ必要があります。

キャストは小数部分を0方向に丸めます。

C#
double value = 12.9;
int result = (int)value; // 12

四捨五入したい場合は、Math.Roundを使います。

C#
double value = 12.9;
int result = (int)Math.Round(value); // 13

切り捨てにはMath.Floor、切り上げにはMath.Ceilingを使います。

C#
double value = 12.3;

double floor = Math.Floor(value); // 12
double ceiling = Math.Ceiling(value); // 13

金額計算では、丸めルールが仕様として決まっていることが多いため、単純なキャストではなく、明示的に丸め処理を書くことが重要です。

8. C#数値型でよくあるエラーと落とし穴

C#数値型では、初心者がつまずきやすいポイントがいくつかあります。特に、doubleの誤差、整数同士の割り算、オーバーフロー、nullの扱いには注意が必要です。

8-1. doubleで0.1を計算すると誤差が出る問題

double0.10.2を計算すると、期待どおりの結果にならないことがあります。

C#
double result = 0.1 + 0.2;
Console.WriteLine(result); // 0.30000000000000004 など

これは、doubleが2進浮動小数点であり、10進数の0.1を正確に表現できないためです。金額計算では、このような誤差が問題になる可能性があります。

C#
decimal result = 0.1m + 0.2m;
Console.WriteLine(result); // 0.3

金額や税率など、10進数としての正確性が必要な値にはdecimalを使いましょう。

8-2. int同士の割り算で小数部分が消える問題

int同士で割り算をすると、結果も整数になります。そのため、小数部分は切り捨てられます。

C#
int a = 5;
int b = 2;

Console.WriteLine(a / b); // 2

2.5を期待していた場合は、どちらか一方をdoubleに変換します。

C#
int a = 5;
int b = 2;

double result = (double)a / b;
Console.WriteLine(result); // 2.5

平均値を計算するときによくあるミスです。

C#
int total = 250;
int count = 4;

double average = (double)total / count;

8-3. オーバーフローで意図しない値になる問題

整数型の範囲を超える計算をすると、オーバーフローが発生します。

C#
int max = int.MaxValue;
int result = max + 1;

Console.WriteLine(result);

オーバーフローが発生すると、文脈によって例外になる場合もあれば、意図しない値になる場合もあります。大きな値を扱う可能性がある場合は、最初からlongを使う、またはcheckedで検出することを検討します。

C#
long safeValue = (long)int.MaxValue + 1;
Console.WriteLine(safeValue);

8-4. checked・uncheckedでオーバーフローを制御する

C#では、checkeduncheckedを使って、整数演算のオーバーフローを制御できます。

checkedを使うと、オーバーフローが発生したときに例外を投げます。

C#
checked
{
int max = int.MaxValue;
int result = max + 1; // OverflowException
}

uncheckedを使うと、オーバーフローを許容します。

C#
unchecked
{
int max = int.MaxValue;
int result = max + 1;
Console.WriteLine(result);
}

数値変換においても、整数型から整数型への変換結果はオーバーフローチェックの文脈に依存します。checkedでは範囲外ならOverflowExceptionが発生し、uncheckedでは変換が実行されます。

実務では、金額、在庫数、請求件数など、オーバーフローが重大な不具合につながる処理ではcheckedを使うと安全です。

8-5. nullを扱いたい場合はnullable型を使う

通常、intdoubleなどの数値型にはnullを代入できません。

C#
// int value = null; // エラー

数値にnullを許可したい場合は、nullable型を使います。

C#
int? age = null;
decimal? price = null;
double? rate = null;

T?は、元の値型Tのすべての値に加えて、追加でnullを表せる型です。たとえばint?は、intの値またはnullを持てます。

値があるかどうかは、HasValueisnull比較で確認できます。

C#
int? age = 30;

if (age.HasValue)
{
Console.WriteLine(age.Value);
}

また、??演算子を使うと、nullの場合の代替値を指定できます。

C#
int? age = null;
int displayAge = age ?? 0;

データベースのNULL値や、未入力のフォーム項目を扱う場合には、nullable型がよく使われます。

9. 実務で失敗しないC#数値型の設計ポイント

実務でC#数値型を選ぶときは、「なんとなく」ではなく、仕様に基づいて判断することが重要です。

9-1. 仕様上の最大値・最小値から型を決める

まず確認すべきなのは、その値が取り得る最大値と最小値です。

たとえば、年齢であればintで十分です。商品数や注文数も、通常はintで問題ありません。

C#
int age = 40;
int orderCount = 120;

一方、累計アクセス数やファイルサイズは、intの範囲を超える可能性があります。

C#
long totalAccessCount = 5_000_000_000L;
long fileSize = 12_000_000_000L;

型を選ぶときは、現在の値だけでなく、将来の増加も考慮しましょう。

9-2. 精度が必要か、速度が必要かで判断する

小数型を選ぶときは、精度と速度のどちらを重視するかを考えます。

doubleは、精度と性能のバランスがよく、一般的な小数計算に向いています。

C#
double average = 75.25;

floatは、精度は落ちますがサイズが小さいため、大量の小数データを扱う場面に向いています。

C#
float x = 10.5f;

decimalは、10進数の正確性が必要な計算に向いています。

C#
decimal amount = 999.99m;

decimalは正確性に優れますが、サイズは16バイトです。floatは4バイト、doubleは8バイトであるため、大量データではメモリ使用量の差が大きくなることがあります。

9-3. 金額計算ではdoubleではなくdecimalを選ぶ

金額計算では、基本的にdecimalを選びます。

C#
decimal unitPrice = 1200m;
int quantity = 3;
decimal subtotal = unitPrice * quantity;

decimal taxRate = 0.10m;
decimal tax = subtotal * taxRate;
decimal total = subtotal + tax;

doubleは2進浮動小数点であり、10進数の小数を正確に表せない場合があります。金額計算では1円単位、小数第2位、税率など、10進数ベースの正確な処理が必要です。

そのため、会計、請求、決済、給与、税金、ECサイトの価格計算では、decimalを使うのが基本です。

9-4. 将来のデータ増加を見越してintとlongを選び分ける

現在はintで十分でも、将来的に値が増える可能性がある場合はlongを検討します。

たとえば、サービス開始直後のユーザー数は少なくても、累計ログ件数やイベント件数は長期運用で大きく増える可能性があります。

C#
long eventLogId = 1;
long totalProcessedCount = 0;

一方で、すべての整数をlongにすればよいわけではありません。年齢、月、日、数量、ページ番号など、明らかに範囲が小さい値はintで十分です。

C#
int month = 6;
int day = 11;
int page = 1;

設計時には、次のように考えるとよいでしょう。

判断選ぶ型
通常の整数int
21億を超える可能性があるlong
DBがBIGINTlong
計算しない識別子stringも検討
金額decimal

9-5. 可読性を重視して不要に小さな型を使わない

メモリ節約のためにbyteshortを使いたくなることがありますが、通常の業務コードでは、不要に小さな型を使わないほうがよい場合もあります。

C#
byte age = 30;   // 技術的には可能
int age2 = 30; // 通常はこちらで十分

byteshortは範囲が狭いため、少し仕様が変わるだけで足りなくなる可能性があります。また、演算時にintとして扱われることもあり、キャストが増える場合があります。

C#
byte a = 10;
byte b = 20;
// byte c = a + b; // 結果はint扱いになるためエラー
byte c = (byte)(a + b);

このようなコードは読みにくくなります。大量の配列やバイナリ処理など明確な理由がある場合を除き、通常の整数にはintを使うのが実務的です。

10. C#数値型に関するよくある質問

10-1. intとlongはどちらを使えばいい?

通常の整数にはintを使います。件数、年齢、回数、点数、ページ番号などはintで十分です。

C#
int count = 100;
int age = 30;

ただし、intの最大値である2,147,483,647を超える可能性がある場合はlongを使います。ファイルサイズ、累計件数、大きなID、データベースのBIGINTなどはlongが向いています。

C#
long fileSize = 5_000_000_000L;

迷った場合は、仕様上の最大値を確認して決めましょう。

10-2. floatとdoubleはどちらを使えばいい?

一般的な小数計算にはdoubleを使います。doublefloatより精度が高く、C#では小数リテラルも標準でdoubleとして扱われます。

C#
double value = 3.14;

floatは、メモリ使用量を抑えたい場合や、大量の小数データを扱う場合に使います。

C#
float value = 3.14f;

ゲーム、画像処理、3D座標、大量データではfloatが選ばれることがありますが、通常の業務アプリケーションではdoubleを基本に考えるとよいです。

10-3. doubleとdecimalは何が違う?

doubleは2進浮動小数点型で、一般的な小数計算に向いています。科学計算、統計、測定値、平均値などで使います。

decimalは10進数の精度が重要な計算に向いています。金額、税率、利率、会計処理などで使います。

C#
double average = 82.5;
decimal price = 1980m;

doubleは高速で広い範囲を扱えますが、10進小数を正確に表せない場合があります。decimalはサイズが大きく計算性能では不利な場合がありますが、10進数の正確性が重要な場面に適しています。

10-4. 金額計算にdecimalを使うべき理由は?

金額計算では、10進数としての正確性が必要だからです。

doubleでは、0.10.2のような値を正確に表せない場合があります。

C#
double x = 0.1 + 0.2;
Console.WriteLine(x); // 0.30000000000000004 など

一方、decimalを使うと、金額計算で期待される10進数の扱いに近くなります。

C#
decimal x = 0.1m + 0.2m;
Console.WriteLine(x); // 0.3

請求、決済、税金、給与、会計などでは、わずかな誤差でも問題になる可能性があります。そのため、金額計算ではdecimalを使うのが基本です。

10-5. C#で一番大きい数値を扱う型は?

組み込み整数型の中で最も大きな範囲を持つものの一つは、符号なし64ビット整数のulongです。ulong0から18,446,744,073,709,551,615まで扱えます。

C#
ulong value = 18_000_000_000_000_000_000UL;

ただし、負の値も扱いたい場合はlongを使います。

C#
long value = 9_000_000_000_000_000_000L;

さらに大きな整数を扱いたい場合は、System.Numerics.BigIntegerを使います。C#リファレンスでも、上限または下限のない符号付き整数を表すにはSystem.Numerics.BigInteger構造体を使用すると説明されています。

C#
using System.Numerics;

BigInteger huge = BigInteger.Parse("999999999999999999999999999999999999");

小数については、非常に広い範囲を扱うならdouble、10進数の精度を重視するならdecimalというように、用途に応じて選びます。

10-6. 数値型の初期値は何になる?

C#の組み込み整数数値型と組み込み浮動小数点数値型の既定値は、どちらも0です。

C#
int intValue = default;
double doubleValue = default;
decimal decimalValue = default;

Console.WriteLine(intValue); // 0
Console.WriteLine(doubleValue); // 0
Console.WriteLine(decimalValue); // 0

nullable型の場合、既定値はnullを表す状態になります。

C#
int? value = default;

Console.WriteLine(value.HasValue); // False

数値型は値型なので、フィールドとして宣言された場合も既定値が入ります。ただし、ローカル変数は使用前に明示的な代入が必要です。

まとめ

C#数値型の選び方は、最初は複雑に見えますが、基本ルールを押さえれば難しくありません。

通常の整数にはintを使います。intに収まらない大きな整数、ファイルサイズ、大量データの件数、大きなIDにはlongを使います。

小数計算では、一般的にはdoubleを使います。ゲームや画像処理、大量の小数データなど、メモリ効率を重視する場面ではfloatを検討します。金額、税率、会計処理など、10進数としての正確性が必要な場面ではdecimalを使います。

特に重要なのは、金額計算にdoubleを使わないことです。doublefloatは高速で便利ですが、10進小数を正確に表せない場合があります。金額や税金のように誤差が許されない値には、decimalを選びましょう。

最後に、数値型を選ぶときは次の4点を確認すると安全です。

  • 小数が必要か

  • 最大値・最小値はどれくらいか

  • 10進数としての正確性が必要か

  • 将来的に値が増える可能性があるか

迷ったときは、整数ならint、大きな整数ならlong、一般的な小数ならdouble、金額ならdecimal。この判断基準を覚えておけば、C#数値型の使い分けで迷う場面は大きく減らせます。