2012-10-10 38 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尤其适用于π值的注释。 –