2012-10-10 82 views
0

我正在製作一個取3個無符號長長函數的函數,並應用餘弦定律來確定三角形是鈍角,銳角還是直角三角形。我應該在使用它們之前將變量加倍加倍嗎?無符號長長算術變爲雙重

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; 

    } 
} 
+0

爲什麼函數採用'unsigned long long'而不是'double'? – Troubadour

回答

2

如果您需要浮點算術,通常沒有理由不能投射。但是,也有一個從unsigned longdouble的隱式轉換,所以您通常也可以在不投射的情況下完成轉換。

在許多情況下,包括你的,只能強制轉換其中一個參數,以便僅對特定操作強制運算double。例如,

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

這樣,除了除法之外的所有操作都是用整數算術計算的,因此速度更快。演員仍然需要在分割時避免截斷。

您的代碼包含浮點參數的比較。但浮點算術幾乎不可避免地降低了準確性。避免有限的準確性,或分析和控制準確性。

  • 身高整數唯一的解決辦法是在一個優越的妹妹回答說明,如果您在您的處置

  • 始終避免從弧度到度的轉換,除了呈現給人類有足夠寬的積分型

  • 從您的數學庫頭文件中取出π的值(不幸的是,這是平臺相關的 - 嘗試_USE_MATH_DEFINES + M_PI或者,如果已經使用boost庫,則爲boost::math::constants::pi<double>()),或者以分析方式表示它。例如,std::atan(1)*2是正確的。

  • 如果您選擇雙精度,並且最終差值小於比如說std::numeric_limits<double>::min() * 8,那麼您可能不會告訴任何關於三角形的信息,並且返回的分類基本上是假的。 (我做了價值8,你可能會失去的方式更多的比特超過三個。)

+0

嗯我早些時候嘗試過,它似乎沒有工作。現在它的工作.....好吧謝謝你的幫助無論如何:) – Painguy

+0

@NimaGanjehloo - 一個可能的解釋是,如果你沒有工作時,在整個部門操作周圍有額外的括號。在這種情況下,您將會輸出截斷的結果。 –

1

你有鈍三角形的一個問題,x*x + y*y - z*z將數學上給出了否定的結果,然後將其還原模2^WIDTH(其中WIDTHunsigned long long中的值位數,至少爲64,可能就是這個數)產生 - 可能是大正值(或在極少數情況下爲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+2yz將被轉換爲標準64位doubles的2^56,xd*xd + yd*yd = 2^58 + 2^112將被評估爲2^112,減去zd*zd然後導致0)。

或者您可以比較x*x + y*yz*z - 或x*xz*z - y*y - 僅使用整數算術。如果x*x可表示爲unsigned long long(我假設0 < x <= y <= z),那麼比較容易,首先檢查(z - y)*(z + y)是否會超過ULLONG_MAX,如果是的話,三角形是鈍的,否則計算和比較。如果x*x不可表示,它就變得複雜了,我認爲最簡單的方法(當然除了使用大整數庫)將分別通過分割計算高位和必要位低64(或任何寬度unsigned long long)位數字在一半的寬度,並比較這些。

進一步注意:您的值爲π,3.14159265太不準確,直角三角形將被報告爲鈍角。

+0

+1尤其適用於π值的註釋。 –