2017-09-25 1 views
1

これは、より大きなプログラムの一部が、私はで開始および終了計算された値のテーブルを生成していると問題が午前部分のみでインクリメント最終値に初期初期値と最終値。何らかの理由で特定の増分値が0.2あるとき、それは完全に正常に動作しますが、与えられた値が0.05あるとき、それは最終的な値が表示されません。ここから計算された値のテーブルを作成しようとすると、所与の数

は、そのセクションの私が持っているコードです:私はvolume <= finalVol + volumeIncrementfor条件を変更した場合

for (volume = initialVol; volume <= finalVol; volume += volumeIncrement) { 

    pressure = pressure_cal(gasNumber, temperature, volume, gasQuantity); 

    printf("%.3lf\t\t\t %.4lf\n", volume, pressure); 
} 

また、それは0.05はなく、0.2のために動作します。

編集:私はのは言わせ、圧力= 1でUSERDEF機能を交換する場合、私はまたことを追加するだろうと思いました。ボリュームの表示値はまったく影響を受けません。

+0

この機能?:*** pressure_cal(gasNumber、温度、体積、gasQuantity); *** –

+0

それする機能であります容積に対する所与の値で圧力の値を計算する。 volumeIncrement(0.2または0.05)だけインクリメントして、最初のボリュームから最後のボリュームまでのすべての可能な圧力値を計算することになっています。 –

+0

多分その機能が働いていないものです.... –

答えて

1

問題は、doubleまたはfloat形式で正確に表現できない派閥を扱う浮動小数点計算の丸め誤差に起因します。 0.2又は0.05のあなたの増分が2の負のべき乗の整数倍であるので、IEEEバイナリ形式の表現は丸みを帯びている:低い値に丸められ

  • volumeIncrement場合volumeになるため、最終的なテストが成功しますfinalVolより小さい小さなビット。これは0.2の場合の処理​​です。
  • volumeIncrementが大きな値に丸められている場合volumefinalVolを超えてしまうため、逆に、最終的なテストは失敗します。これは0.05の場合の処理​​です。

この問題を回避するために複数の方法があります。

  • あなたは、最終的な比較が成功したことを確認するためにvolumeに小さな値を追加することができます。volume <= finalVol + volumeIncrement/2はこれを実現するための簡単な方法だろう。
  • あなたは、整数算術演算を使用して計算のみのためではなく、列挙のための浮動小数点に変換することができます。たとえば、リテールの小数点数の代わりにミリリットルの整数を使用し、20または5の増分を使用します。
  • 増分の代わりにステップ数を指定できます。ここ

最後のアプローチのために修正されたコードである:

int steps = 100; 
for (int step = 0; step <= steps; step++) { 
    double volume = initialVol + (finalVol - initialVol) * step/steps; 
    double pressure = pressure_cal(gasNumber, temperature, volume, gasQuantity); 
    printf("%.3f\t\t\t %.4f\n", volume, pressure); 
} 
関連する問題