C ++:余弦是错的,应该是零。 3PI / 2

时间:2014-03-24 02:36:20

标签: c++ double cosine

我有一个程序,我正在尝试计算cos(M_PI*3/2)而不是得到0,我应该得到-1.83691e-016

我在这里缺少什么?我需要的是弧度。

4 个答案:

答案 0 :(得分:5)

数字M_PI只是π的近似值。你得到的余弦也是一个近似值,它是一个相当不错的余弦 - 它在小数点后面有十五个正确的数字。

答案 1 :(得分:5)

首先,M_PI不是一个非常便携的宏,并且通常对大约15个小数位有好处,这取决于你使用的编译器 - 我的猜测是你正在使用微软的C ++编译器。

其次,如果您想要更准确(和可移植)的版本,请使用Boost Math库: http://www.boost.org/doc/libs/1_55_0/libs/math/doc/html/math_toolkit/tutorial/non_templ.html

第三,正如Kay指出的那样,pi本身就是一个无理数,因此没有多少比特(或基数10中的数字)就足以准确地表示它。因此,你实际计算的不是cos(3 * pi / 2),而是“给定所需位的pi的最接近的近似值的3/2的余弦”,这不是3 * pi / 2和因此不会为零。

最后,如果您想要数学常量的自定义精度,请阅读:http://www.boost.org/doc/libs/1_55_0/libs/math/doc/html/math_toolkit/tutorial/user_def.html

答案 2 :(得分:4)

鉴于double值的离散性,测试数字相等性的标准误差范围为numeric_limits<double>::epsilon()

#include <iostream>
#include <limits>
#include <cmath>

using namespace std;

int main()
{
  double x = cos(M_PI*3/2);
  cout << "x = << " << x << endl;
  cout << "numeric_limits<double>::epsilon() = "
       << numeric_limits<double>::epsilon() << endl;
  cout << "Is x sufficiently close to 0? "
       << (abs(x) < numeric_limits<double>::epsilon() ? "yes" : "no") << endl;
  return 0;
}

输出:

x = << -1.83697e-16
numeric_limits<double>::epsilon() = 2.22045e-16
Is x sufficiently close to 0? yes

如您所见,-1.83697e-16的绝对值在epsilon 2.22045e-16给出的误差范围内。

答案 3 :(得分:2)

Pi是不合理的,计算机无法完美地代表数字。 pi的“正确”值的小误差导致输出中的错误。为1.83691×10 -16 关闭仍然相当不错。

如果您想了解更多有关实际系统的限制以及输入中的小错误的影响,请参阅http://en.wikipedia.org/wiki/Numerical_stability