0

符号なしのロングロングを3つ取り、余弦定理を適用して、三角形が鈍角、鋭角、直角三角形のいずれであるかを調べる関数を作成しています。変数を使用する前に、変数をdoubleにキャストする必要がありますか?

void triar( unsigned long long& r, 
            unsigned long long x, 
            unsigned long long y, 
            unsigned long long z ) 
{
  if(x==0 || y==0 || z==0) die("invalid triangle sides");

  double t=(x*x + y*y -z*z)/(2*x*y);

  t=acos (t) * (180.0 / 3.14159265);

  if(t > 90) {
    cout<<"Obtuse Triangle"<<endl;
    r=t;

  } else if(t < 90){
    cout<<"Acute Triangle"<<endl;
    r=t;

  } else if(t == 90){
    cout<<"Right Traingle"<<endl;
    r=t;

  }
}
4

2 に答える 2

2

一般に、浮動小数点演算が必要な場合にキャストできなかった理由はありません。unsigned longただし、からへの暗黙の変換もあるdoubleため、キャストせずに完全に行うこともできます。

多くの場合、あなたを含めdoubleて、特定の操作でのみ算術演算を強制するために引数の1つだけをキャストできます。例えば、

double t = (double)(x*x + y*y - z*z) / (2*x*y)

このように、除算を除くすべての演算は整数演算で計算されるため、わずかに高速になります。分割中の切り捨てを回避するために、キャストは引き続き必要です。

コードには、浮動小数点引数の比較が含まれています。ただし、浮動小数点演算では、ほぼ必然的に精度が低下します。制限された精度を回避するか、精度を分析および制御します。

  • あなたが自由に使える十分に広い積分型を持っているなら、優れた姉妹の答えで説明されているように整数のみの解決策を好む

  • 人間への提示を除いて、ラジアンから度への変換は常に避けてください

  • 数学ライブラリヘッダーファイルからπの値を取得するか(残念ながら、これはプラットフォームに依存します。_USE_MATH_DEFINES+M_PIを試してください。すでにブーストライブラリを使用している場合は、boost::math::constants::pi<double>())、分析的に表現してください。たとえば、std::atan(1)*2は直角です。

  • 倍精度を選択し、最終的な差の値がたとえば、よりも小さい場合、std::numeric_limits<double>::min() * 8おそらく三角形について何も言えず、返される分類は基本的に偽物です。(私は8の値を作成しましたが、3ビットよりもはるかに多くのビットを失う可能性があります。)

于 2012-10-10T22:23:39.117 に答える
1

鈍角三角形に問題があり、x*x + y*y - z*z数学的に負の結果が得られます。これはモジュロで減少し2^WIDTH(ここで、は少なくとも64WIDTHの値のビット数であり、おそらく正確にそれです)、おそらく大きな正の値(またはまれに)が生成されます。unsigned long longケース0)。その場合、の計算結果はt = (x*x + y*y - z*z)/(2*x*y)1より大きくなる可能性がありacos(t)、NaNを返します。

三角形が与えられた引数タイプで鈍角/鋭角/直角三角形であるかどうかを確認する正しい方法はx*x + y*y < /* > / == */ z*z、数学的な結果が範囲を超えていないことを確認できるかどうかを確認することunsigned long longです。

それがわからない場合はdouble、計算前に変数をに変換することができます。

double xd = x, yd = y, zd = z;
double t = (xd*xd + yd*yd - zd*zd)/(2*xd*yd);

精度が低下し、ほぼ直角三角形の結果が正しくなくなる可能性があります(たとえば、わずかに鈍角の三角形x = 2^29, y = 2^56-1, z = 2^56+2の場合、両方ともy標準のz64ビットで2 ^ 56に変換されdoublexd*xd + yd*yd = 2^58 + 2^112に評価され2^112、減算するzd*zdと結果は0になります)。

または、整数演算のみを使用して-または-と比較x*x + y*yすることもできます。が(と思います)として表現できる場合は、比較的簡単です。最初に、三角形が鈍角であるかどうかを確認します。そうでない場合は、計算して比較します。表現できない場合は複雑になります。最も簡単な方法は(もちろん、大きな整数ライブラリを使用する場合を除いて)、数値をで分割することにより、上位64ビット(または必要に応じて下位64ビット)を個別に計算することです。幅の半分とそれらを比較します。z*zx*xz*z - y*yx*xunsigned long long0 < x <= y <= z(z - y)*(z + y)ULLONG_MAXx*xunsigned long long

さらに注意してください:πの値3.14159265は不正確すぎます。直角三角形は鈍角として報告されます。

于 2012-10-11T00:31:41.377 に答える