2012-01-17 6 views
3

ボールを箱に収める関数を作っています。箱の各辺に収まるボールの数を計算するコードは以下の通りです。ボールがあたかもキューブのようにまとまっていると仮定します。私はこれが最適な方法ではないことを知っていますが、ちょうどそれと一緒に行く。Cで二重切り捨てと数学の問題

問題は私が4.0000000 * 4.0000000 * 2.000000のような数字を得るが、製品は32の代わりに31であるということです。

さらに2つのものがあります。このエラーは、最適な辺の長さに達した場合にのみ発生します。例えば、辺の長さは12.2、ボックスの厚さは.1、ボールの半径は1.5です。これは正確に4つのボールがその側に収まるように導く。私がintとしてキャストしなければ、それは動くが、intとしてキャストした場合、私は前述のエラー(32ではなく31)を得る。また、印刷ラインは、辺の長さが最適であれば1回、そうでない場合は2回実行されます。私はそれが何を意味するのか分かりません。

double ballsFit(double r, double l, double w, double h, double boxthick) 
{ 
double ballsInL, ballsInW, ballsInH; 
int ballsinbox; 

ballsInL= (int)((l-(2*boxthick))/(r*2)); 
ballsInW= (int)((w-(2*boxthick))/(r*2)); 
ballsInH= (int)((h-(2*boxthick))/(r*2)); 
ballsinbox=(ballsInL*ballsInW*ballsInH); 
printf("LENGTH=%f\nWidth=%f\nHight=%f\nBALLS=%d\n", ballsInL, ballsInW, ballsInH, ballsinbox); 
return ballsinbox; 
} 
+0

4.0 * 4.0 * 2.0の積は実際には32.0であるべきですが、 '(l-(2 * boxthick))/(r * 2)'は制限された精度と四捨五入に関しては本当に4.0を得て3.9999999浮動小数点数の誤差。 –

答えて

6

浮動小数点数学は不正確です。

たとえば、0.1(問題のある例では太さの値として言及しています)は、正確にはdoubleとして表すことはできません。変数に0.1を代入すると、格納されるのは近似 0.1です。

What Every Computer Scientist Should Know About Floating-Point Arithmeticを読むことをお勧めします。

4.0000000 * 4.0000000 * 2.000000のような数値が得られますが、製品は32ではなく31です。

ほとんどの場合、被乗数(少なくともそれらのいくつか)は、それらがどのように見えるのかわかりません。それらが正確に 4.0,4.0、および2.0の場合、その製品は正確に 32.0になります。ダブルスが表すことができるすべての桁を印刷した場合、3.99999999999 ...などのように9をたくさん見ることができると確信しています。その結果、製品は32未満です。 2倍から整数への変換では分数部分が切り捨てられるだけなので、31で終わることになります。

もちろん、より小さい数字は、より小さくなります。 よりも大きい数字をよりも多く得ることができます。

+0

+1それは良い紙です、それは本当に戻ってきました。 – thkala

+0

'...彼らは見た目に似ていません':Javaの場合、デフォルトの 'Double.toString()'メソッドが最も小さい桁数でもっとも曖昧でない10進数に丸めます。 '17.17'の実際の価値が何であるかを推測する気に? – thkala

+0

17.1700000000000017053025658242404460906982421875 –

1

最新のコンピュータでよく使用されるIEEE-754などの固定精度浮動小数点数は、正確に10進数をすべて表すことができません。1/3は10進数で正確に表現できません。

たとえば、0.1は、0.100000000000000004...の行に沿ったもので、バイナリに変換して戻すことができます。違いは小さく、重要です。

私は時々、このような問題に対処するために、拡張精度または任意精度の算術演算を使用して精度を維持し、計算結果をdoubleに変換して最終結果を得ました。通常はパフォーマンスが著しく低下しますが、IMHOの正確さは無限に重要です。

最近、高精度算術ライブラリhereのアルゴリズムを使用して、精度と性能の両方の面で優れた結果を得ました。

関連する問題