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;

  }
}
4

2 回答 2

2

如果您需要浮点运算,通常没有理由不进行转换。但是,也存在从unsigned longto的隐式转换double,因此您通常也可以完全不进行强制转换。

在许多情况下,包括您的情况,您只能强制转换其中一个参数以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 的值,你可能会丢失比 3 更多的位。)

于 2012-10-10T22:23:39.117 回答
1

你有钝角三角形的问题,x*x + y*y - z*z在数学上会给出一个否定的结果,然后减少模2^WIDTH(其中WIDTH的值位数是unsigned 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+2,两者yz都将转换为标准 64 位doubles 的 2^56,xd*xd + yd*yd = 2^58 + 2^112将被评估为2^112,然后减去zd*zd结果为 0)。

或者您可以仅使用整数算术x*x + y*y比较z*z- 或x*x- 。z*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太不准确,直角三角形将被报告为钝角。

于 2012-10-11T00:31:41.377 回答