2016-09-11 8 views
4

浮動小数点を取る関数がありますが、計算結果をできるだけ正確に保ちたいと思います。私はあなたが2つの浮動小数点数を掛け合わせると、有効数字の倍数を倍増することを読んでいます。浮動小数点数を掛けて倍精度精度を維持する/取得する

したがって、浮動小数点数が2倍になると、たとえばfloat e, f;となり、私はdouble g = e * fとなると、いつビットが切り捨てられますか?

私の例の機能では、キャスティングが必要ですか?はいの場合はどこですか?これはきつい内部ループにあります。もし各変数の周りにstatic_cast<double>(x)を置くと、a b c dが使われていますが、私は5-10%減速します。しかし、私は各変数を別々にキャストする必要はないと思っています。またはここでダブルを返すと、とにかく私に何の利得も与えていないと私だけでフロートを返すことができますか?

double func(float a, float b, float c, float d) { 
    return (a - b) * c + (a - c) * b; 
} 
+1

他のオペランドがあなたのために変換されるので、1つのキャストのみが必要です_ "どちらかのオペランドが倍精度で、もう一方のオペランドが倍精度に変換される" _ source:http://en.cppreference.com/w/cpp/ language/operator_arithmetic#Conversionsしかし、これはあなたに同じ減速を与えるでしょう。ダブルを返すことに関する2番目の質問は、返された結果で何をするかによって異なります。 –

+0

私の場合、両方の(すべての)オペランド(戻り値の型を除く)は浮動小数点ですか? – Ela782

+1

どこでも 'double'を使用すると、パフォーマンスが向上します(とにかく精度が向上します)。これにより、変換のオーバーヘッドが節約されます。 – 5gon12eder

答えて

5

キャストなしで2つの浮動小数点数を掛けると、結果は浮動小数点精度(すなわち切り捨てられた)で計算され、次にdoubleに変換されます。

結果をdoubleで計算するには、少なくとも1つのオペランドを最初にdoubleにキャストする必要があります。次に、計算全体が2倍で行われます(そして、すべての浮動小数点値が変換されます)。しかし、それは同じ減速を作成します。減速は、数値を浮動小数点から倍精度に変換することが完全に自明ではない(異なるビット・サイズと指数部とマンタの範囲)ためです。

私はこれを行い、関数の定義を制御していれば、すべての引数をdoubleとして渡すことができます(私は一般的にdoubleをどこでも使用します、現代のコンピュータではfloatとdoubleの計算の速度差は無視できますが、大きな値の配列で操作する場合のメモリスループットとキャッシュのパフォーマンスのみが問題になります)。

Btw。正確さのために重要なケースは実際には乗算ではなく、精度が大きな差を生むことができる加減算です。 1e + 6と1e-3の加算/減算を検討してください。

+0

最初の3つの文章は完全に私の答えです質問!他の情報も非常に便利です。 – Ela782

4

5~10%減速よりも意味が重要です。私は何をしたい:

double func_impl(double a, double b, double c, double d) { 
    return (a - b) * c + (a - c) * b; 
} 

double func(float a, float b, float c, float d) { 
    return func_impl(a, b, c, d); 
} 

私はそれはあなたもあなたの計算に倍精度をしたいという考えを表現し、ちょうどインターフェイス上の山車を必要とするので、それは、少し遅くなります場合でも、これを選択すると思います。あなたの機能の本体をキャスティングから分離したままにします(後者は1つのステップで実行されます)。

関連する問題