-1。#IND00为正根的结果

时间:2011-12-13 09:59:58

标签: c math

以下是代码:

double angle( double *vec1 , double *vec2 ){
    return acos( ( *vec1 * *vec2 + *(vec1+1) * *(vec2+1) + *(vec1+2) * *(vec2+2) ) / ( sqrt( pow( *vec1 , 2 ) + pow( *(vec1+1) , 2 ) + pow( *(vec1+2) , 2 ) ) * sqrt( pow( *vec2 , 2 ) + pow( *(vec2+1) , 2 ) + pow( *(vec2+2) , 2 ) ) ) );
}

输入的矢量:<1,1,1> , <2,2,2>

返回angle: -1.#IND00

你能告诉我,有什么不对吗?

这是代码“可读”:

arcCos[ (x1*x2 + y1*y2 + z1*z2) / sqrt(x1^2 + y1^2 + z1^2) * sqrt(x2^2 + y2^2 + z2^2) ]

2 个答案:

答案 0 :(得分:2)

你的计算结果应该计算出acos(1),你给出的数字应该是0.然而,1是在acos(x)允许范围的最顶部给出真实结果,任何更高的东西都会很复杂(或者在大多数情况下都会产生某种错误)。

我的猜测是你得到的浮点数略大于引起问题的浮点数。原因是每个人的朋友浮点舍入错误。

当使用您的计算方法时,您将最终得到的股息是两个平方根的乘积。在这种情况下,平方根将是sqrt(3)和sqrt(12)。当相乘时,它们将给出一个整数--6。但是,如果这两个数字都略微向下舍入以使它们适合浮点,那么当它们相乘时它们可能会略微小于6.然后最终得到6(在顶部)由略小于6的东西划分,这会给你略大于一的东西。

尝试降低此风险的一种方法是将计算更改为:

sqrt((x1^2 + y1^2 + z1^2) * (x2^2 + y2^2 + z2^2))

这导致sqrt只在产品上进行一次,更有可能产生正确的结果。

答案 1 :(得分:1)

好的......在这里......问题是由于数学: - )

首先我重构了你的代码:

double angle( double *vec1 , double *vec2 ){

  // sqlen = 6
  double sqlen =  vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2]; 

  // sqpow1 = 3
  double sqpow1 = pow( vec1[0] , 2 ) + pow( vec1[1] , 2 ) + pow( vec1[2] , 2 );

  // sqpow2 = 12
  double sqpow2 = pow( vec2[0] , 2 ) + pow( vec2[1] , 2 ) + pow( vec2[2] , 2 );

  // 6/(sqrt(3)*sqrt(12)) = 1
  return acos( sqlen / ( sqrt(sqpow1) * sqrt(sqpow2) ) );
}

这应该返回'0',因为acos(1)明确定义为0.; - )