int型の変数に入ったint型の最大値int.MaxValueに1を足すとcheckedコンテキストだとOverflowException 例外が起きます。
では、クイズです。
float型の変数に入ったfloat型の最大値float.MaxValueに1を足すと何が起こるでしょうか
- checkedコンテキストならOverflowException 例外
- ∞になる
- 最小値に戻る
- 値は変化しない
答は【値は変化しない】です。
なぜでしょう?
float型のような【浮動小数点型】は小数点を移動させることで極大値、極小値に対応します。そのため、有効桁数が限られるため、小さすぎる値は反映されなくなります。
1は小さすぎないだろう……と言いたい気持ちは分かりますが、floatの最大値3.4028235掛ける10の38乗と比較すると、ゴミのように小さな値になります。
もし、1を足す代わりに2を掛けると、結果は∞になります。極大値に2を掛けると、極大値+極大値ということになって極大値以上の極大値になるからです。数学的に正しい結果ではありませんが、表現可能な範囲を超えてしまったことを示しています。
罠の数々 §
- 数値の表現力を限界まで使うといろいろ不思議なことが起こる。小さな値で上手く行った方法が大きな値でも通用するとは限らない。注意しよう
参考リンク §
checked (C# リファレンス)
Int32.MaxValue フィールド
OverflowException クラス
Single.MaxValue フィールド
int型はInt32という名前になっていることに注意しよう。名前が違うのはC#と.NETでの名前に差があるからだ。ではSingleは実際には何型だろうか。上記リンクから確かめてみよう。
リポジトリ §
https://github.com/autumn009/cshowto
floatMaxPlusOne §
using System;
class Program
{
static void Main()
{
checked
{
try
{
int a = int.MaxValue;
for (int i = 0; i < 5; i++)
{
Console.WriteLine(a);
a++;
}
}
catch (OverflowException e)
{
Console.WriteLine(e.Message);
}
try
{
float a = float.MaxValue;
for (int i = 0; i < 5; i++)
{
Console.WriteLine(a);
a++;
}
}
catch (OverflowException e)
{
Console.WriteLine(e.Message);
}
}
}
}
実行結果
2147483647
Arithmetic operation resulted in an overflow.
3.4028235E+38
3.4028235E+38
3.4028235E+38
3.4028235E+38
3.4028235E+38