数値型 C#での基礎知識

基本用法

数値型の基本

プログラミングで数値は重要ですが、算数や数学の世界とは扱いがちょっと違う
ここではC#言語で数値を扱うのに必要なあれこれをまとめて紹介してます

C#(.NET)の数値型は構造体として定義されている
int型はC#の型であり、.NET型でのSystem.Int32構造体の別名
数値型のデフォルト値はいづれも0

int num = 10;
System.Int32 num = 10;
C# 型 範囲 サイズ .NET 型
sbyte -128 ~ 127 符号付き 8 ビット System.SByte
byte 0 ~ 255 符号なし 8 ビット System.Byte
short -32,768 ~ 32,767 符号付き 16 ビット System.Int16
ushort 0 ~ 65,535 符号なし 16 ビット System.UInt16
int -2,147,483,648 ~ 2,147,483,647 符号付き 32 ビット System.Int32
uint 0 ~ 4,294,967,295 符号なし 32 ビット System.UInt32
long -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 符号付き 64 ビット System.Int64
ulong 0 ~ 18,446,744,073,709,551,615 符号なし 64 ビット System.UInt64
このほかにSystem.Numerics.BigInteger構造体という範囲制限ない符号付き整数を表す構造体がある
BigInteger 構造体 (System.Numerics)
任意の大きい符号付き整数を表します。

数値リテラル

10進 プレフィックスなし
16進 0x または0Xプレフィックス
バイナリ ob または 0Bプレフィックス
符合なし u または U サフィックス
long型 lまはたサフィックス

区切り文字

C#7.0以降で追加された仕様
桁区切り文字としてアンダースコアが使える 任意の場所に挿入されたアンスコが桁区切りとして使える
// 以下は同じ値 可読性だけ違う
int val1 = 123456789;
int val2 = 123_456_789:

Mathクラス

算術演算用にSystem.Mathクラスが便利メソッドを提供している
以下はその一部
var ret1 = Math.Abs(-10);       // 10 絶対値 10
var ret2 = Math.Ceiling(12.34); // 13 指定値以上の最少整数値
var ret3 = Math.Floor(12.34);   // 12 指定値以下の最大整数値
var ret4 = Math.Max(10, 15);    // 15 指定値で大きい方
var ret5 = Math.Min(10, 15);    // 10 指定値で小さい方
var ret6 = Math.Round(12.34);   // 12 五捨六入
Math クラス (System)
三角関数、対数関数、およびその他の一般的な数学関数の定数と静的メソッドを提供します。

数値と文字列型との変換

int型を例にしているが他の数値型も基本的には同じ


// 文字列を数値に変換する例(数値に変換不能な文字列が指定されたら例外)
int number1 = int.Parse("100");
int number2 = Convert.ToInt32("100");
 
// 文字列が数値に変換できるかを確認し可能な場合はその数値、不可の場合はNull
Func<string, int?> func = (str) => int.TryParse(str, out int value) ? (int?)value : null;

int? number3 = func("100"); // 100
int? number4 = func("");     // null;
 
// 数値を文字列に変換
string str1 = 100.ToString();
string str2 = System.Convert.ToString(100);

除算は最後に

2 / 3 * 3 ≠ 2 * 3 / 3
演算は左から順に行われる。2 / 3 は 0.5 だが剰余は切り捨てられて0となりこれに3を掛けても0
int ret1 = 2 / 3 * 3;  // 0
int ret2 = 2 * 3 / 3;  // 2

型変換 暗黙の変換とキャスト

// 桁数の大きい型へは暗黙の変換が可能  
short s = 10;
int i = s;

// 桁数の小さい型へはキャストすれば変換可能
long l1 = int.MaxValue;              // 2147483647
int i1 = (int)val20;                 // 2147483647

// 桁あふれは想定外の値となるから要注意
long l2 = (long)int.MaxValue + 1;    // 2147483648
int i2 = (int)val21;                 // -2147483648

浮動小数点型の誤差の問題

0.1など2進数で表せないことから誤差の集積が問題となりえる。

float f1 = 0;
decimal d1 = 0;

for(int cnt = 0 ; cnt < 100 ; ++cnt)
{
    f1 += 0.1f;     // 10.0000019
    d1 += 0.1m;     // 10
}

オーバーフローのチェック

checkedキーワード指定すると桁あふれ時は例外がスローされる
// 定数値のみの場合はコンパイル不可
//int value1 = 2147483647 + 1;
//int value1 = int.MaxValue + 1;

// 桁溢れで不正値となる
int one = 1;
int value2 = 2147483647 + one; // -2147483648
 
checked
{
    // checked内では桁あふれ時にOverflowException がスローされる
    int value3 = 2147483647 + one;
}