2010-12-02 10 views
2

浮動小数点演算で問題が発生していますが、正確ではありません。私は、すべての入力変数が次の重要な変数の約20倍も重くなる重み付き公式に基づいてスコアを計算しようとしています。しかし、入力は実数なので、結果を格納するためにdoubleを使用してしまいました。以下のコードでは、E1とE2の違いを失うという問題があります。C++の浮動小数点演算での丸めの問題を回避する方法は?

このコードはパフォーマンスに影響を受けますので、この問題に対する効率的な答えを見つける必要があります。私は入力を100倍にしてからintを使うことを考えましたが、それは最善の解決策なので疑問です。

#include <iostream> 

int main() 
{ 
    double score1, score2; 
    float a = 2.75 ; 
    float b = 5.25 ; 
    float c = 5.25 ; 
    float d = 2.75 ; 
    float E1 = 3 ; 
    float E2 = 6 ; 

    score1 = 20 * b - 1 * a + 0.05 * d /* - 0.0025 * c*/ + 0.0001 * E1 ; 
    score2 = 20 * b - 1 * a + 0.05 * d /* - 0.0025 * c*/ + 0.0001 * E2 ; 

    std::cout << score1 << std::endl; 
    std::cout << score2 << std::endl; 

    std::cin.get(); 
    return 0; 
} 

//ouputs: 
//102.388 
//102.388 
+0

浮動小数点は、すなわち、それはすべての浮動小数点数を表すことができない、それについての情報の多くがあります、限られています。 – Drakosha

+1

ダブルを使用できます。非常に特殊な状況に陥っていない限り、問題にはなりません。 –

答えて

4
  1. あなたがあなたのスコア計算に必要なのですかどのように多くの有効桁数cout << setprecision(number_of_digits) << score1 << endl;
  2. を使用し、全体の値を出力していませんか?
+0

おかげさまで、より高い精度を設定しました。正しい値が表示されます。これは、 'if(score1 nus

+0

2フロートを比較すると、 –

+0

私が愚かである場合、申し訳ありませんが、デバッグログに間違った値が表示された場合、最初に想定するのは、実際には間違っているということです。 – nus

3

私は(それは私が考えるに十分正確であろうから)百によって私の入力を乗算して、int型を使用するのではと思ったが、私はそれは考える

最適なソリューションです疑いますあなたが示した価値は、私はそうだと言います。

+0

実際に入力に100を掛けても機能しません。入力が整数であってもすべての計算結果が整数になるわけではありません。入力を10000または1000000倍して、計算の定数を変更する必要があります。 –

1

http://ideone.com/qqTB3は差は失ったが、(二重のための15桁である浮動小数点精度、まで)あなたが期待するよう、実際に同じ大きされていないことを示します。

+0

私をideone.comに紹介するための+1 – nus

1

は、このコードで何が起こっているか見てみましょう:

score1 = 20 * b - 1 * a + 0.05 * d /* - 0.0025 * c*/ + 0.0001 * E1 ; 

// Multiplication division happens first: 

float tmp1 = static_cast<float>(20) * b;  // 20 cast to float. 
float tmp2 = static_cast<float>(1) * a;  // 1 cast to float. 
double tmp3 = 0.05 * static_cast<double>(d); // d converted to double as 0.05 is double 
double tmp4 = 0.0001 * static_cast<double>(E1);// E1 cast to double as 0.0001 is double 

// Addition and subtraction now happen 
float tmp5 = tmp1 - tmp2; 
double tmp6 = static_cast<double>(tmp5) + tmp3; // tmp5 cast to double as tmp3 is a double. 
double tmp7 = tmp6 + tmp4; 
score1  = tmp7; 

私たちは私たちの頭でこれを行う場合は、次の

tmp1 = 105.0 
tmp2 = 2.75 
tmp3 = 0.1375 
tmp4 = 0.0003 
tmp5 = 107.75 
tmp6 = 107.8875 
tmp7 = 107.8878 
精度がそれらの値のために保持する必要があり


しかし、あなたは、プリントアウトしたときに倍精度のデフォルトの精度は小数点以下3桁です。

std::cout << 107.8878; 
> 107.888 

ので、精度を設定します。

std::cout << std::setprecision(15) << 107.8878 << "\n"; 
> 107.8878 
+0

うーん、それほどパフォーマンスが悪くない...良い方法がありますか? – nus

+0

それは非常に完璧な(それは言葉ではない)と見えないのはどういう意味ですか?これは、コンパイラがコードを生成する方法とまったく同じです。一時変数はおそらくレジスタになり、オプティマイザは操作の順序を(ある程度まで)入れ替えることができますが、これはまさに基礎となるコードが行うことになります。 –

+0

私が見せようとしてきたことは、あなたの操作のほとんどがダブルスで行われていることです。したがって、非常に特殊なスペースが必要な場合を除いて、変数はおそらく倍になるはずです。 –

関連する問題