C#で計算機イプシロンを計算する

C言語での計算機イプシロンを確認する方法を見つけたので、C#でも実行してみることにしました。

計算機イプシロン

Machine Epsilon

正数εに対して1+εという演算を行ったとき、記憶領域は有限なのでεが小さすぎると無視されるが、無視されないで加えられる尤も小さい数をマシン・エプシロンと呼んでいる。

実際に値を1.0から半分にしていくと、浮動小数点数の表現上1.0とその値を足しても1.0とみなされる場合が出てきます。そのときの1.0と足して1.0とならない直前の値が計算機イプシロンです。

C#で小数を表す基本の型はfloatdoubledecimalがあるので、すべてについてみていきます。プログラムは単純に型を変えるだけなので、まとめて出してしまいます。ソースコード等はこちらから

	static void CalcFloatEpsilon()
	{
		float eps = 1.0f;

		while (1.0f + eps / 2.0f > 1.0f)
		{
			eps /= 2.0f;

			Console.WriteLine($"{(1.0f + eps):e30}");
		}

		Console.WriteLine($"1+eps  : {(1.0f + eps):e30}");
		Console.WriteLine($"1+eps/2: {(1.0f + eps / 2.0f):e30}");
		Console.WriteLine($"float machine epsilon: {eps:e30}");
	}

	static void CalcDoubleEpsilon()
	{
		double eps = 1.0;

		while (1.0 + eps / 2.0 > 1.0)
		{
			eps /= 2.0;

			Console.WriteLine($"{(1.0 + eps):e30}");
		}

		Console.WriteLine($"1+eps  : {(1.0 + eps):e30}");
		Console.WriteLine($"1+eps/2: {(1.0 + eps / 2.0):e30}");
		Console.WriteLine($"double machine epsilon: {eps:e30}");
	}

	static void CalcDecimalEpsilon()
	{
		decimal eps = 1.0m;

		while (1.0m + eps / 2.0m > 1.0m)
		{
			eps /= 2.0m;

			Console.WriteLine($"{(1.0m + eps):e30}");
		}

		Console.WriteLine($"1+eps  : {(1.0m + eps):e30}");
		Console.WriteLine($"1+eps/2: {(1.0m + eps / 2.0m):e30}");
		Console.WriteLine($"decimal machine epsilon: {eps:e30}");
	}

計算結果は次の通りです。(長い…)

1.500000000000000000000000000000e+000
1.250000000000000000000000000000e+000
1.125000000000000000000000000000e+000
1.062500000000000000000000000000e+000
1.031250000000000000000000000000e+000
1.015625000000000000000000000000e+000
1.007812500000000000000000000000e+000
1.003906250000000000000000000000e+000
1.001953130000000000000000000000e+000
1.000976560000000000000000000000e+000
1.000488280000000000000000000000e+000
1.000244140000000000000000000000e+000
1.000122070000000000000000000000e+000
1.000061040000000000000000000000e+000
1.000030520000000000000000000000e+000
1.000015260000000000000000000000e+000
1.000007630000000000000000000000e+000
1.000003810000000000000000000000e+000
1.000001910000000000000000000000e+000
1.000000950000000000000000000000e+000
1.000000480000000000000000000000e+000
1.000000240000000000000000000000e+000
1.000000120000000000000000000000e+000
1+eps  : 1.000000120000000000000000000000e+000
1+eps/2: 1.000000000000000000000000000000e+000
float machine epsilon: 1.192092900000000000000000000000e-007

1.500000000000000000000000000000e+000
1.250000000000000000000000000000e+000
1.125000000000000000000000000000e+000
1.062500000000000000000000000000e+000
1.031250000000000000000000000000e+000
1.015625000000000000000000000000e+000
1.007812500000000000000000000000e+000
1.003906250000000000000000000000e+000
1.001953125000000000000000000000e+000
1.000976562500000000000000000000e+000
1.000488281250000000000000000000e+000
1.000244140625000000000000000000e+000
1.000122070312500000000000000000e+000
1.000061035156250000000000000000e+000
1.000030517578125000000000000000e+000
1.000015258789062500000000000000e+000
1.000007629394531300000000000000e+000
1.000003814697265600000000000000e+000
1.000001907348632800000000000000e+000
1.000000953674316400000000000000e+000
1.000000476837158200000000000000e+000
1.000000238418579100000000000000e+000
1.000000119209289600000000000000e+000
1.000000059604644800000000000000e+000
1.000000029802322400000000000000e+000
1.000000014901161200000000000000e+000
1.000000007450580600000000000000e+000
1.000000003725290300000000000000e+000
1.000000001862645100000000000000e+000
1.000000000931322600000000000000e+000
1.000000000465661300000000000000e+000
1.000000000232830600000000000000e+000
1.000000000116415300000000000000e+000
1.000000000058207700000000000000e+000
1.000000000029103800000000000000e+000
1.000000000014551900000000000000e+000
1.000000000007276000000000000000e+000
1.000000000003638000000000000000e+000
1.000000000001819000000000000000e+000
1.000000000000909500000000000000e+000
1.000000000000454700000000000000e+000
1.000000000000227400000000000000e+000
1.000000000000113700000000000000e+000
1.000000000000056800000000000000e+000
1.000000000000028400000000000000e+000
1.000000000000014200000000000000e+000
1.000000000000007100000000000000e+000
1.000000000000003600000000000000e+000
1.000000000000001800000000000000e+000
1.000000000000000900000000000000e+000
1.000000000000000400000000000000e+000
1.000000000000000200000000000000e+000
1+eps  : 1.000000000000000200000000000000e+000
1+eps/2: 1.000000000000000000000000000000e+000
double machine epsilon: 2.220446049250313100000000000000e-016

1.500000000000000000000000000000e+000
1.250000000000000000000000000000e+000
1.125000000000000000000000000000e+000
1.062500000000000000000000000000e+000
1.031250000000000000000000000000e+000
1.015625000000000000000000000000e+000
1.007812500000000000000000000000e+000
1.003906250000000000000000000000e+000
1.001953125000000000000000000000e+000
1.000976562500000000000000000000e+000
1.000488281250000000000000000000e+000
1.000244140625000000000000000000e+000
1.000122070312500000000000000000e+000
1.000061035156250000000000000000e+000
1.000030517578125000000000000000e+000
1.000015258789062500000000000000e+000
1.000007629394531250000000000000e+000
1.000003814697265625000000000000e+000
1.000001907348632812500000000000e+000
1.000000953674316406250000000000e+000
1.000000476837158203125000000000e+000
1.000000238418579101562500000000e+000
1.000000119209289550781250000000e+000
1.000000059604644775390625000000e+000
1.000000029802322387695312500000e+000
1.000000014901161193847656250000e+000
1.000000007450580596923828125000e+000
1.000000003725290298461914062500e+000
1.000000001862645149230957031200e+000
1.000000000931322574615478515600e+000
1.000000000465661287307739257800e+000
1.000000000232830643653869628900e+000
1.000000000116415321826934814400e+000
1.000000000058207660913467407200e+000
1.000000000029103830456733703600e+000
1.000000000014551915228366851800e+000
1.000000000007275957614183425900e+000
1.000000000003637978807091713000e+000
1.000000000001818989403545856500e+000
1.000000000000909494701772928200e+000
1.000000000000454747350886464100e+000
1.000000000000227373675443232000e+000
1.000000000000113686837721616000e+000
1.000000000000056843418860808000e+000
1.000000000000028421709430404000e+000
1.000000000000014210854715202000e+000
1.000000000000007105427357601000e+000
1.000000000000003552713678800500e+000
1.000000000000001776356839400200e+000
1.000000000000000888178419700100e+000
1.000000000000000444089209850000e+000
1.000000000000000222044604925000e+000
1.000000000000000111022302462500e+000
1.000000000000000055511151231200e+000
1.000000000000000027755575615600e+000
1.000000000000000013877787807800e+000
1.000000000000000006938893903900e+000
1.000000000000000003469446952000e+000
1.000000000000000001734723476000e+000
1.000000000000000000867361738000e+000
1.000000000000000000433680869000e+000
1.000000000000000000216840434500e+000
1.000000000000000000108420217200e+000
1.000000000000000000054210108600e+000
1.000000000000000000027105054300e+000
1.000000000000000000013552527200e+000
1.000000000000000000006776263600e+000
1.000000000000000000003388131800e+000
1.000000000000000000001694065900e+000
1.000000000000000000000847033000e+000
1.000000000000000000000423516500e+000
1.000000000000000000000211758200e+000
1.000000000000000000000105879100e+000
1.000000000000000000000052939600e+000
1.000000000000000000000026469800e+000
1.000000000000000000000013234900e+000
1.000000000000000000000006617400e+000
1.000000000000000000000003308700e+000
1.000000000000000000000001654400e+000
1.000000000000000000000000827200e+000
1.000000000000000000000000413600e+000
1.000000000000000000000000206800e+000
1.000000000000000000000000103400e+000
1.000000000000000000000000051700e+000
1.000000000000000000000000025800e+000
1.000000000000000000000000012900e+000
1.000000000000000000000000006400e+000
1.000000000000000000000000003200e+000
1.000000000000000000000000001600e+000
1.000000000000000000000000000800e+000
1.000000000000000000000000000400e+000
1.000000000000000000000000000200e+000
1.000000000000000000000000000100e+000
1+eps  : 1.000000000000000000000000000100e+000
1+eps/2: 1.000000000000000000000000000000e+000
decimal machine epsilon: 1.000000000000000000000000000000e-028

各型でのεをまとめると下のようになります。

計算機イプシロン(ε)
float 1.192092900000000000000000000000e-007
double 2.220446049250313100000000000000e-016
decimal 1.000000000000000000000000000000e-028

ISOに準拠しているためfloatとdoubleはC言語など、他の言語のときと同じ結果となっています。
さすがのdecimalという感じで、decimalの正の最小の数字がそのままεとなっています。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です