c++ - Sin 和 Cos 为众所周知的角度提供意想不到的结果

标签 c++ floating-point trigonometry cmath

我确信这是一个非常愚蠢的问题,但是当我将 180 度角传递给 c/c++ 的 cos() 和 sin() 函数时,我似乎收到了一个不正确的值。我知道它应该是: 0.0547 的正弦和 0.99 的余弦 但我得到 3.5897934739308216e-009 的 sin 和 -1.00000 的 cos

我的代码是:

double radians = DegreesToRadians( angle );
double cosValue = cos( radians );
double sinValue = sin( radians );

DegreesToRadians() 是:

double DegreesToRadians( double degrees )
{ 
    return degrees * PI / 180; 
} 

谢谢你:)

最佳答案

C/C++提供了sin(a)cos(a)tan(a)等需要参数的函数使用弧度单位而不是double DegreesToRadians(d) 执行的转换接近,但在转换结果四舍五入时是近似值。机器 M_PI 也很接近,但与数学无理数 π 的值不同。

180 的 OP 代码传递给 DegreesToRadians(d),然后传递给 sin()/cos(),结果与预期不同由于四舍五入、double() 的有限精度以及 PI 可能的弱值。

一项改进是在调用 trig 函数之前以度数 执行参数缩减。下面先将角度减小到 -45° 到 45° 范围内,然后调用 sin()。这将确保 sind(90.0*N) --> -1.0, 0.0, 1.0 中的 N 值较大。 .注意:sind(360.0*N +/- 30.0) 可能不完全等于 +/-0.5。需要一些额外的考虑。

#include <math.h>
#include <stdio.h>

static double d2r(double d) {
  return (d / 180.0) * ((double) M_PI);
}

double sind(double x) {
  if (!isfinite(x)) {
    return sin(x);
  }
  if (x < 0.0) {
    return -sind(-x);
  }
  int quo;
  double x90 = remquo(fabs(x), 90.0, &quo);
  switch (quo % 4) {
    case 0:
      // Use * 1.0 to avoid -0.0
      return sin(d2r(x90)* 1.0);
    case 1:
      return cos(d2r(x90));
    case 2:
      return sin(d2r(-x90) * 1.0);
    case 3:
      return -cos(d2r(x90));
  }
  return 0.0;
}

int main(void) {
  int i;
  for (i = -360; i <= 360; i += 15) {
    printf("sin()  of %.1f degrees is  % .*e\n", 1.0 * i, DBL_DECIMAL_DIG - 1,
        sin(d2r(i)));
    printf("sind() of %.1f degrees is  % .*e\n", 1.0 * i, DBL_DECIMAL_DIG - 1,
        sind(i));
  }
  return 0;
}

输出

sin()  of -360.0 degrees is   2.4492935982947064e-16
sind() of -360.0 degrees is  -0.0000000000000000e+00  // Exact

sin()  of -345.0 degrees is   2.5881904510252068e-01  // 76-68 = 8 away
//                            2.5881904510252076e-01
sind() of -345.0 degrees is   2.5881904510252074e-01  // 76-74 = 2 away

sin()  of -330.0 degrees is   5.0000000000000044e-01  // 44 away
//  0.5                       5.0000000000000000e-01
sind() of -330.0 degrees is   4.9999999999999994e-01  //  6 away

sin()  of -315.0 degrees is   7.0710678118654768e-01  // 68-52 = 16 away
// square root 0.5 -->        7.0710678118654752e-01
sind() of -315.0 degrees is   7.0710678118654746e-01  // 52-46 = 6 away

sin()  of -300.0 degrees is   8.6602540378443860e-01
sind() of -300.0 degrees is   8.6602540378443871e-01
sin()  of -285.0 degrees is   9.6592582628906842e-01
sind() of -285.0 degrees is   9.6592582628906831e-01
sin()  of -270.0 degrees is   1.0000000000000000e+00  // Exact
sind() of -270.0 degrees is   1.0000000000000000e+00  // Exact
...

关于c++ - Sin 和 Cos 为众所周知的角度提供意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31502120/

相关文章:

c++ - 从 int 到 longlong 的危险转换 : No warning?

floating-point - Fortran 中具有 NaN 值的参数(常量)变量

c - arctan(x) 函数给出错误答案

c++ - 结构作为C++中的参数

c++ - QTableView/QTableWidget 中类似 Ktorrent 的小部件

获取公共(public)库文件夹的 CSIDL 的 C++ Shell 函数

java - 使用 Java 迭代所有浮点值

c++ - C++ 中的减法 double

Java如何使图形对象朝其面向的方向移动

确定绕圆移动的两个点是否接近或分离的算法