アンダーフローという言葉の指す範囲が謎

  • このエントリーをはてなブックマークに追加

スポンサーリンク

※サイト運営にサーバーは必須です※
~このサイトもエックスサーバーを使用しています~

はじめに

アンダーフローという言葉を調べたが、どこまでの範囲をアンダーフローというかよくわからなくなってきた。

自分がわかったこと、逆にわからなかったことをまとめておく。

アンダーフローとは

・演算の結果の絶対値が小さくなった時に、正確に表現できない状態
・「下位桁溢れ」とも言う

以下の場合、アンダーフローというのだろうか?

1番目のケース:0に近いが0でない小さな数字が、0として表示される
2番目のケース:0に近いが0でない小さな数字が、不正確に表示される
3番目のケース:大きな数字に対して。小さな数字を足しても反映されない

1番目のケース:0に近いが0でない小さな数字が、0として表示される

float型であれば、1.401298E-45 (float型で表現できる最も0に近い小さな数字)より小さい数字を表現しようとした時に、0と表示される「場合がある」。

例えば、10の-46乗をfloat型で表現しようと試みた時に、0と表示される。

※ここで、「場合がある」というぼやけた表現を使ったのは10の-45乗という1.401298E-45より小さな数字を取り扱っても、0にならなかったため。プログラムの動きを見ると、1.401298E-45の半分以下になった時に、0と表示されている。

2番目のケース:0に近いが0でない小さな数字が、不正確に表示される

float型は2^(-127乗)より小さい数になると、精度が悪くなる。(10進法に直すと10の-38乗オーダーより小さい領域)。

※どうして精度が悪くなるかという理由については、以下の記事を参照してください。この後の議論では、この記事で書かれている程度のことはわかっている前提で進める。

 

例えば、10の-45乗を表示しようとしても、結果は1.401298E-45となる。0.4 E-45分ずれている。これは不正確である。

この場合、float型は10の-45乗を表現できていると言っていいのだろうか?

そして、このケースをアンダーフローと言っていいのだろうか?

この部分は、人によって意見が分かれそうな部分である。

仮にこの場合をアンダーフローと言っていいのなら、以下のような疑問がわく。

疑問1:2^(-127乗)より小さい数をアンダーフローと言っていいのか?

例えば、以下のサイトは、非正規化数(float型であれば2^(-127乗)より小さい領域)でしか表現できない状況は、アンダーフローに含まれるという定義をしている

 

疑問2:非正規化数で、ピッタリ表現できる数字を宣言した時に、アンダーフローと言っていいのか?

例えば、1.401298E-45という数字を宣言した時に、この数字は2^(-127乗)より小さい数だが、ピッタリ表現できている。この時、アンダーフローが起きているといっていいのか?

もしも、この場合に対しては、アンダーフローが起きていないと主張するなら、許される精度はどこまでか?

1.401298E-45を表示しようとして、1.401298E-45と表示されるのはアンダーフローか?
1.40E-45を表示しようとして、1.401298E-45と表示されるのはアンダーフローか?
1.39E-45を表示しようとして、1.401298E-45と表示されるのはアンダーフローか?
1.30E-45を表示しようとして、1.401298E-45と表示されるのはアンダーフローか?
1.0E-45を表示しようとして、1.401298E-45と表示されるのはアンダーフローか?

3番目のケース:大きな数字に対して。小さな数字を足しても反映されない

例えば、float型であれば10の7乗(10000000)に対して、1を足しても10000001とはならず、10000000である。

アンダーフローが、扱う数値が細かくて、正しく扱えていないこと意味するのであれば、この状況はアンダーフローというのか?

結局、どこまでがアンダーフロー?

1番目のケース:0に近いが0でない小さな数字が、0として表示される
2番目のケース:0に近いが0でない小さな数字が、不正確に表示される
3番目のケース:大きな数字に対して。小さな数字を足しても反映されない

1番目のケースはアンダーフローと言っても問題ない。アンダーフローの記事をいくつか見たが、このケースこそがアンダーフローであると主張する記事もあった。

2番目のケースと3番目のケースはよくわからない。人によって言っていることがぶれている。私も何を信じればいいのかわからない。

ソースコード(言語はC#)

実行結果

1.401298E-45
1.401298E-45
0
0
1000001
1E+07
1.000001
1
100000000000001
1E+15

※以上のソースコードをコンパイルする時に、「演算のオーバーフローおよびアンダーフローのチェック」の項目にチェックを入れてみたが、何も警告されなかった。

「演算のオーバーフローおよびアンダーフローのチェック」の項目にチェックを入れる方法は以下の記事を参照してください。

無料体験レッスンあり。マンツーマン形式で初心者向け。
  • このエントリーをはてなブックマークに追加

スポンサーリンク

コメントを残す

*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)