はじめに
C# の数値型は色々種類があります。
- クラス名と短縮名がある(
int
等の組み込み型) - 読み取り専用の値型
- 実行環境に依存せず同じサイズ(ポインタ型
nint
nuint
を除く)
整数型
型名 | 短縮名 | sizeof() |
10 進数桁数 | 備考 |
---|---|---|---|---|
System.Byte |
byte |
1 | 3 | 符号なし |
System.SByte |
sbyte |
1 | 3 | |
System.Int16 |
short |
2 | 5 | |
System.UInt16 |
ushort |
2 | 5 | 符号なし |
System.Int32 |
int |
4 | 10 | |
System.UInt32 |
uint |
4 | 10 | 符号なし |
System.Int64 |
long |
8 | 19 | |
System.UInt64 |
ulong |
8 | 20 | 符号なし |
System.Int128 |
- | 16 | 39 | .NET 7 で導入 |
System.UInt128 |
- | 16 | 39 | .NET 7 で導入、符号なし |
System.IntPtr |
nint |
4 または 8 | - | ポインタ、実行環境依存 |
System.UIntPtr |
nuint |
4 または 8 | - | ポインタ、実行環境依存、符号なし |
浮動小数点数型
型名 | 短縮名 | sizeof() |
10 進数桁数 | 備考 |
---|---|---|---|---|
System.Half |
- | 2 | - | .NET 5 で導入 |
System.Single |
float |
4 | - | |
System.Double |
double |
8 | - | |
System.Decimal |
decimal |
16 | 29 |
128bit 整数とかあったんですねえ・・・ 初めて知りました。
テストコード
テストコード
using Xunit;
public class __NumericsTest
{
[Fact]
public void SizeOf()
{
Assert.Equal(1, sizeof(byte));
Assert.Equal(1, sizeof(sbyte));
Assert.Equal(2, sizeof(short));
Assert.Equal(2, sizeof(ushort));
Assert.Equal(4, sizeof(int));
Assert.Equal(4, sizeof(uint));
Assert.Equal(8, sizeof(long));
Assert.Equal(8, sizeof(ulong));
unsafe
{
Assert.Equal(16, sizeof(Int128));
Assert.Equal(16, sizeof(UInt128));
}
unsafe
{
Assert.Equal(2, sizeof(Half));
}
Assert.Equal(4, sizeof(float));
Assert.Equal(8, sizeof(double));
Assert.Equal(16, sizeof(decimal));
// 実行環境依存
// unsafe
// {
// Assert.Equal(8, sizeof(nint));
// Assert.Equal(8, sizeof(nuint));
// }
}
[Fact]
void NumberOfDecimalDigits()
{
int GetNumberOfDecimalDigits(Int128 maxValue)
{
var result = 1;
for (; result < 100; result++)
{
maxValue /= 10;
if (maxValue == 0)
break;
}
return result;
}
int GetNumberOfDecimalDigitsU(UInt128 maxValue)
{
var result = 1;
for (; result < 100; result++)
{
maxValue /= 10;
if (maxValue == 0)
break;
}
return result;
}
Assert.Equal(3, GetNumberOfDecimalDigits(byte.MaxValue));
Assert.Equal(3, GetNumberOfDecimalDigits(sbyte.MaxValue));
Assert.Equal(5, GetNumberOfDecimalDigits(short.MaxValue));
Assert.Equal(5, GetNumberOfDecimalDigits(ushort.MaxValue));
Assert.Equal(10, GetNumberOfDecimalDigits(int.MaxValue));
Assert.Equal(10, GetNumberOfDecimalDigits(uint.MaxValue));
Assert.Equal(19, GetNumberOfDecimalDigits(long.MaxValue));
Assert.Equal(20, GetNumberOfDecimalDigits(ulong.MaxValue));
Assert.Equal(39, GetNumberOfDecimalDigits(Int128.MaxValue));
Assert.Equal(39, GetNumberOfDecimalDigitsU(UInt128.MaxValue));
Assert.Equal(5, GetNumberOfDecimalDigits((Int128)Half.MaxValue));
Assert.Equal(39, GetNumberOfDecimalDigits((Int128)float.MaxValue));
Assert.Equal(39, GetNumberOfDecimalDigits((Int128)double.MaxValue));
Assert.Equal(29, GetNumberOfDecimalDigits((Int128)decimal.MaxValue));
}
static void Sqrt(Performance p)
{
p.AddTest("Math", () =>
{
var sum = 0.0;
for (int i = 0; i < 1000000; i++)
sum += Math.Sqrt(i);
});
p.AddTest("MathF", () =>
{
var sum = 0.0f;
for (int i = 0; i < 1000000; i++)
sum += MathF.Sqrt(i);
});
}
}
その他
System.Numerics 名前空間に様々なクラスが用意されています。以下は一部を抜粋
- BigInteger: 任意の大きさを持つ符号付き整数を表します。
- Complex: 複素数を表します。
- Vector2: 2 つの単精度浮動小数点値を持つベクトルを表します。
System.Math
は数学系のメソッドが用意されています(Sqrt()
Cos()
)。
System.MathF
はその float
バージョンで、数値の精度が低くても良い場合はこちらを検討できます。
おわりに
.NET Framework 時代にはなかった型がちらほら追加されています。マイナーな数値型を使う機会は限定されそうですが、知ってるとスマートに解決できるケースもありそうです(あった)。