我怎样才能解决在C ++中sin(M_PI)不为0的事实?

时间:2010-04-19 21:22:40

标签: c++ trigonometry cosine cmath

在C ++中,

const double Pi = 3.14159265;
cout << sin(Pi);                          // displays: 3.58979e-009

它应该显示数字

我理解这是因为Pi被近似了,但是有没有什么方法可以让Pi硬编码到我的程序中,为sin(Pi)返回0? (可能是一个不同的常数?)

如果你想知道我想要做什么:我将极性转换为矩形,虽然有一些printf()技巧我可以将其打印为“0.00”,但它仍然没有始终返回体面的价值(在某些情况下,我得到“-0.00”)

需要sin和余弦的行是:

x = r*sin(theta);
y = r*cos(theta);

BTW:我的矩形 - &gt;极地工作正常...它只是极地 - &gt;矩形

谢谢!

编辑:我正在寻找一种解决方法,以便我可以将sin(Pi的一些倍数)作为一个很好的整数打印到控制台(理想情况下没有一千个if语句)

14 个答案:

答案 0 :(得分:28)

What Every Computer Scientist Should Know About Floating-Point Arithmetic(编辑:也在评论中链接)是非常铁杆阅读(我不能声称已经阅读了所有内容),但其关键在于:你永远不会完美准确的浮点计算。来自文章:

将无限多个实数压缩成有限数量的位需要近似表示。

不要让程序依赖于浮点计算的精确结果 - 始终允许公差范围。仅供参考3.58979e-009约为0.0000000036。这完全在你选择的任何合理的公差范围内!

答案 1 :(得分:15)

我们这样说吧,3.58979e-009 接近为0,因为3.14159265值是真正的Pi。从技术上讲,你得到的是你所要求的。 :)

现在,如果您只输入9个有效数字(小数点后8位),则指示输出也不再显示,即使用:

cout.precision(8);
cout << sin(Pi);

答案 2 :(得分:4)

您是否尝试过大多数<cmath><math.h>实施中提供的M_PI?

即便如此,以这种方式使用浮点也总会引入一定量的错误。

答案 3 :(得分:4)

这应该显示为零:

cout << fixed << sin(Pi);

(我认为你不应该试图解决任何问题。如果你担心显示,请处理显示功能,而不是处理值本身。)

答案 4 :(得分:3)

3.58979e-009这是0,0000000358979

是~~ 0和你一样~~ PI。

答案 5 :(得分:3)

如果您的相等运算符具有足够的容差

,则它等于零

答案 6 :(得分:2)

你可以输入更多的数字来获得更好的结果(例如尝试3.1415926535897932384626433832795029L),但你仍会得到舍入误差。

但是,您仍然可以创建自己的sincos版本来检查已知的Pi值,并在这些情况下返回零。

namespace TrigExt
{
    const double PI = 3.14159265358979323846;

    inline double sin(double theta)
    {
        return theta==PI?(0.0):(std::sin(theta));
    }
}

你也可以为其他三角函数展开这个东西并处理Pi倍数。

答案 7 :(得分:1)

你可以编写一个小包装函数:

double mysin(const double d) {
    double ret = sin(d);
    if(fabs(ret) < 0.0000001) {
        return 0.0;
    } else {
        return ret;
    }
}

正如其他人所说,浮点数学是众所周知的不精确。如果你想让某些东西看起来完全为零,你需要某种宽容。

答案 8 :(得分:1)

为什么不强迫你需要多少数字?

 int isin = (int)(sin(val) * 1000);
 cout << (isin/1000.0)

答案 9 :(得分:1)

对于精确的PI值,

sin(PI)应该等于0。您没有输入PI的确切值。正如其他人指出的那样,你将四舍五入到小数点后7位的结果为0,这对你的近似值非常有利。

如果您需要不同的行为,您应该编写自己的正弦函数。

答案 10 :(得分:0)

如果在数学运算中使用float或double,则永远不会得到确切的结果。 原因是在计算机中,所有内容都存储为2的幂。这并不完全转换为我们的十进制数系统。 (一个例子是在基数2中有n个表示为0.1)

另外,在某些编译器和平台上,float和double至少是64位。 (我想 - 如果需要的话,有人会纠正我)。对于非常大的值或非常小的值(0.0000000000xxx)

,这将导致一些舍入误差

为了获得准确的结果,您将需要一些大整数库。

如上述问题的评论所述,请参阅网站...... http://docs.sun.com/source/806-3568/ncg_goldberg.html

答案 11 :(得分:0)

double cut(double value, double cutoff=1e-7) {
  return (abs(value) > cutoff)*value;
}

这将零值低于阈值,使用它像cut(sin(Pi))

答案 12 :(得分:-1)

更重要的数字可能有所帮助。我的C编译器(gcc)在“math.h”中对M_PI使用常量3.14159265358979323846。除此之外,没有太多选择。创建自己的函数来验证答案(如问题的另一个答案中所述)可能是最好的主意。

答案 13 :(得分:-1)

你知道,只是因为那里的数学正确性:sin(3.14159265) ins't 为零。它大约零,这正是程序告诉你的。对于计算,这个数字应该给你一个好的结果。对于显示,它很糟糕,因此每当您打印浮动时,请确保格式化数字。

我真的不认为这里的工作有浮动机制......这只是简单的数学。

关于代码,但要小心......不要通过在显示之前进行近似来使代码给出错误的结果,只是以正确的方式显示信息。