ここでの問題は、float
変数 ( ) を使用しているのに、それを定数 ( )gap
と比較していることです。定数は、特に指定がない限り、C の浮動小数点定数は double であるためです。double
0.00002
double
根本的な問題は、数値がまたは0.00002
で表現できないことです。(1/3 の 10 進展開のように、2 進展開は無限に長いため、2 進浮動小数点ではまったく表現できません。) したがって、プログラムを記述すると、C コンパイラは に非常に近い値に置き換えます。同様に、数値を変数に読み込むと、に非常に近い値に置き換えられます。数値は よりもビット数が多いため、値は よりも値に近くなります。float
double
0.00002
double
0.00002
scanf
0.00002
float
float
0.00002
double
floats
double
0.00002
float
精度の異なる 2 つの浮動小数点値を比較すると、コンパイラは精度の低い値を正確に同じ値に変換し、精度を高めます。( として表現可能なdouble
値の集合は、 として表現可能な値の集合のスーパーセットであるため、 aの値と同じ値を持つfloat
a を常に見つけることができます。) そして、が実行されるとこうなります:は に変換されます。同じ値であり、それが double (close to) と比較されます。これらの値はどちらも実際には 0.00002 よりわずかに小さく、 の方が近いため、は より小さくなります。double
float
gap < 0.00002
gap
double
0.00002
double
float
double
この問題は、いくつかの方法で解決できます。まず、 a を作成してフォーマットをに変更するか、 gap
aと比較することで、変換を回避できます。double
scanf
%lf
gap
float
while (gap < 0.00002F || gap > 0.99999F) {
しかし、いくつかの理由から、それは正しくありません。まず、C コンパイラによる浮動小数点変換が標準ライブラリによる変換と同じであるという保証は実際にはありませんscanf
(実装定義の方法で選択された、最も近い表現可能な値のすぐ隣にある小さい表現可能な値。」(どちらの値が生成されるかは詳細に指定されていませんscanf
が、最も近い表現可能な値であることをお勧めします。) たまたま、gcc
( glibc
Linux で使用される C コンパイラと標準ライブラリ) どちらも最も近い表現可能な値を生成しますが、他の実装ではしないでください。
とにかく、エラー メッセージによると、値を から の間にする必要が0.00001
あり1.00000
ます。したがって、テストは正確に次のようにする必要があります。
while (gap <= 0.00001F || gap >= 1.0000F) { ...
gap
(あなたがとして保持すると仮定しますfloat
。)
上記の解決策のいずれかが機能します。個人的には、比較をより直感的にするためにgap
adouble
を作成し、比較を and と比較するように変更し0.00001
ます1.0000
。
ちなみにE-05
接尾辞は「10 の -5 乗」というE
意味ですExponent
。あなたはそれをたくさん見るでしょう。これは、浮動小数点定数を記述する標準的な方法です。