最近、私は投稿を読んでいました: Herb Sutter による GOTW からの Double or Nothing 以下のプログラムの説明に少し混乱しています:
int main()
{
double x = 1e8;
while( x > 0 )
{
--x;
}
}
このコードが、あるマシンで 1 秒間実行されると仮定します。このようなコードはばかげているという点には同意します。
ただし、x
からfloat
に変更した場合の問題に関する説明によるdouble
と、一部のコンパイラでは、コンピューターが永久に実行され続けます。説明は、標準からの次の引用に基づいています。
C++ 標準のセクション 3.9.1/8 からの引用:
浮動小数点型には、float、double、long double の 3 つがあります。double 型は少なくとも float と同じ精度を提供し、型 long double は少なくとも double と同じ精度を提供します。float 型の値のセットは、double 型の値のセットのサブセットです。double 型の値のセットは、long double 型の値のセットのサブセットです。
コードの質問は次のとおりです。
「double」を「float」に変更すると、どのくらいの時間がかかると予想されますか? なんで?
与えられた説明は次のとおりです。
float が 0 から 1e8 までのすべての整数値を正確に表現できるかどうかに応じて、おそらく約 1 秒 (特定の実装では、float は double よりも速いか、同じくらい速いか、または遅いかもしれません) かかるか、永遠にかかります。
上記の標準からの引用は、double で表現できるが float では表現できない値が存在する可能性があることを意味します。特に、一部の一般的なプラットフォームやコンパイラでは、double は [0,1e8] のすべての整数値を正確に表すことができますが、float はできません。
float が 0 から 1e8 までのすべての整数値を正確に表現できない場合はどうなるでしょうか? その後、変更されたプログラムはカウントダウンを開始しますが、最終的には表現できない値 N に到達し、 N-1 == N (浮動小数点の精度が不十分なため)...そして
私の質問は:
float が を表すことさえできない場合1e8
は、初期化時にすでにオーバーフローが発生しているはずfloat x = 1e8
です。では、どうしてコンピュータを永遠に動かすことができるのでしょうか?
ここで簡単な例を試しました(そうではありませんdouble
がint
)
#include <iostream>
int main()
{
int a = 4444444444444444444;
std::cout << "a " << a << std::endl;
return 0;
}
It outputs: a -1357789412
これは、コンパイラが指定された数値をint
型で表現できない場合、オーバーフローが発生することを意味します。
じゃあ読み間違えた?私が逃したポイントは何ですか?x
から未定義の動作に変更されdouble
ていますか?float
ありがとうございました!