1

float 変数にエッジが含まれていないときに、ユーザーに 1.00000 から 0.00001 までの数値を入力させようとしています。ユーザーがドットの後に 5 つ以上の数字を入力していないと推測できます。今、ここに私が書いたものがあります:

printf("Enter required Leibniz gap.(Between 0.00001 to 1.00000)\n");
scanf("%f", &gap);
while ((gap < 0.00002) || (gap > 0.99999))
{
printf("Enter required Leibniz gap.(Between 0.00001 to 1.00000)\n");
scanf("%f", &gap);
}

今、可能な限り最小の数値を入力しているときに、0.00002 が while ループでスタックしてしまいます。デバッガーを実行すると、0.00002 がこの値と共に float 変数に格納されていることがわかりました: 1.99999995e-005 誰でも私が間違っていることを明確にすることができますか? 0.00002 が条件を満たさないのはなぜですか? この「1.99999995e-005」って何?

4

4 に答える 4

3

ここでの問題は、float変数 ( ) を使用しているのに、それを定数 ( )gapと比較していることです。定数は、特に指定がない限り、C の浮動小数点定数は double であるためです。double0.00002double

根本的な問題は、数値がまたは0.00002で表現できないことです。(1/3 の 10 進展開のように、2 進展開は無限に長いため、2 進浮動小数点ではまったく表現できません。) したがって、プログラムを記述すると、C コンパイラは に非常に近い値に置き換えます。同様に、数値を変数に読み込むと、に非常に近い値に置き換えられます。数値は よりもビット数が多いため、値は よりも値に近くなります。floatdouble0.00002double0.00002scanf0.00002floatfloat0.00002doublefloatsdouble0.00002float

精度の異なる 2 つの浮動小数点値を比較すると、コンパイラは精度の低い値を正確に同じ値に変換し、精度を高めます。( として表現可能なdouble値の集合は、 として表現可能な値の集合のスーパーセットであるため、 aの値と同じ値を持つfloata を常に見つけることができます。) そして、が実行されるとこうなります:は に変換されます。同じ値であり、それが double (close to) と比較されます。これらの値はどちらも実際には 0.00002 よりわずかに小さく、 の方が近いため、は より小さくなります。doublefloatgap < 0.00002gapdouble0.00002doublefloatdouble

この問題は、いくつかの方法で解決できます。まず、 a を作成してフォーマットをに変更するか、 gapaと比較することで、変換を回避できます。doublescanf%lfgapfloat

while (gap < 0.00002F || gap > 0.99999F) {

しかし、いくつかの理由から、それは正しくありません。まず、C コンパイラによる浮動小数点変換が標準ライブラリによる変換と同じであるという保証は実際にはありませんscanf(実装定義の方法で選択された、最も近い表現可能な値のすぐ隣にある小さい表現可能な値。」(どちらの値が生成されるかは詳細に指定されていませんscanfが、最も近い表現可能な値であることをお勧めします。) たまたま、gcc( glibcLinux で使用される C コンパイラと標準ライブラリ) どちらも最も近い表現可能な値を生成しますが、他の実装ではしないでください。

とにかく、エラー メッセージによると、値を から の間にする必要が0.00001あり1.00000ます。したがって、テストは正確に次のようにする必要があります。

while (gap <= 0.00001F || gap >= 1.0000F) { ...

gap(あなたがとして保持すると仮定しますfloat。)

上記の解決策のいずれかが機能します。個人的には、比較をより直感的にするためにgapadoubleを作成し、比較を and と比較するように変更し0.00001ます1.0000

ちなみにE-05接尾辞は「10 の -5 乗」というE意味ですExponent。あなたはそれをたくさん見るでしょう。これは、浮動小数点定数を記述する標準的な方法です。

于 2013-11-09T01:58:30.013 に答える
2

floats は、考えられるすべての数値の正確な値を格納することはできません (0 から 1 の間の無限の数値のため、不可能です)。float に 0.00002 を割り当てると、実際に発生している実装により、異なるが非常に近い数値になります。数値が大きくなるにつれて精度が低下します。

したがって、2 つの近いフロートを直接比較して健全な結果を得ることはできません。

浮動小数点の詳細については、このウィキペディアのページ を参照してください

あなたができることは、固定小数点演算をエミュレートすることです。を内部int n = 100000;的に表現1.00000 し (1000 -> 0.001 など)、それに応じて計算を行うか、固定小数点演算ライブラリを使用します。

于 2013-11-09T01:03:42.857 に答える
0

一部のコメントが言ったように、浮動小数点数の表現方法が原因で、このようなエラーが表示されます。これに対する解決策は、それをに変換することです

gap + 1e-8 < 0.0002 

これにより、合格したいほとんどのケースと失敗したくないほとんどのケースを許容するのに十分な小さな許容範囲が得られます

于 2013-11-09T01:06:07.807 に答える