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

C++ C++;:余弦是错误的,应该是零。3Pi/2,c++,double,trigonometry,C++,Double,Trigonometry,我有一个程序,我试图计算cos(m_PI*3/2),而不是得到0,我应该得到-1.83691e-016 我错过了什么?我的弧度是我需要的 这个数M_PI只是π的近似值。你得到的余弦也是一个近似值,它是一个非常好的值——小数点后有15个正确的数字。Pi是无理的,计算机无法完美地表示数字。pi“正确”值的小误差会导致输出中的误差。1.83691×10-16关仍然很好 如果您想进一步了解实际系统的限制以及输入中小错误的影响,请参阅。鉴于双值的离散性,测试数值相等性的标准误差范围是数值限制::epsil

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


我错过了什么?我的弧度是我需要的

这个数
M_PI
只是π的近似值。你得到的余弦也是一个近似值,它是一个非常好的值——小数点后有15个正确的数字。

Pi是无理的,计算机无法完美地表示数字。pi“正确”值的小误差会导致输出中的误差。1.83691×10-16关仍然很好


如果您想进一步了解实际系统的限制以及输入中小错误的影响,请参阅。

鉴于
值的离散性,测试数值相等性的标准误差范围是
数值限制::epsilon()

#包括
#包括
#包括
使用名称空间std;
int main()
{
双x=cos(μPI*3/2);

首先,MyPI不是一个非常便携的宏,通常是15位小数,这取决于你使用的编译器——我猜你是在使用微软的C++编译器。 其次,如果您想要一个更精确(更便携)的版本,请使用Boost数学库:

第三,正如Kay所指出的,pi本身是一个无理数,因此任何位数(或以10为底的位数)都不足以精确表示它。因此,你实际计算的不是精确的cos(3*pi/2),而是“给定所需位数,pi的最接近值的3/2倍余弦”,它不会是3*pi/2,因此不会为零


最后,如果您想要自定义数学常数的精度,请阅读以下内容:

您的
M_PI*3/2
值不足以接近3π/2以获得0。为M_PI设置了什么值?即使
M_PI*3/2
的计算结果与实数3π/2最接近,这可能离
cos
不应返回0。指向@user2059300的强制链接一种可能性不是计算中间值的结果,而是保留符号。这在C(++)中非常复杂,但在prolog中非常简单。无论如何,不要对浮点值使用
==
,而是始终测试是否接近某个ε。在数学中,它有22个有效数字。可能远没有足够的精度来期望此计算为0.0。@cplusplusooa和double只能表示约16个十进制数字,因此22位ts太多了。@Kay这在很大程度上取决于使用哪种编译器。例如,今天的64位世界支持的位数比32位编译器多。IEEE-754标准解决浮点问题。这里有一个Wikipedia摘要:。完整的标准在IEEE网站上提供,但除非IEEE成员或当前注册,否则可能不是免费的在一个工程学位项目中担任领导。另外,请查看此高级总结。10-16的ε非常小,非常接近于零。换句话说,有必要确定一个可接受的精度,然后对照它进行检查。我只想指出,
数值限制::ε
被定义为1.0 a之间的差值根据类型指定下一个可表示的值。这适用于像OP这样的小数字,但对于大数字,可能需要不同的ε。
#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