我如何解决在 C++ 中,sin(M_PI) 不为 0 的事实?

发布于 2024-08-29 14:59:18 字数 591 浏览 7 评论 0原文

在 C++ 中,

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

它应该显示数字零

我理解这是因为 Pi 正在被近似,但是有什么方法可以将 Pi 值硬编码到我的程序中,该值将为 sin(Pi) 返回 0 吗? (也许是不同的常量?)

如果您想知道我想要做什么:我正在将极坐标转换为矩形,虽然我可以使用一些 printf() 技巧将其打印为“0.00”,但它仍然不能始终返回合适的值(在某些情况下我得到“-0.00”)

需要正弦和余弦的行是:

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

顺便说一句:我的矩形 - > Polar 工作正常...只是 Polar ->长方形

谢谢!

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

In C++,

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

it SHOULD display the number zero

I understand this is because Pi is being approximated, but is there any way I can have a value of Pi hardcoded into my program that will return 0 for sin(Pi)? (a different constant maybe?)

In case you're wondering what I'm trying to do: I'm converting polar to rectangular, and while there are some printf() tricks I can do to print it as "0.00", it still doesn't consistently return decent values (in some cases I get "-0.00")

The lines that require sin and cosine are:

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

BTW: My Rectangular -> Polar is working fine... it's just the Polar -> Rectangular

Thanks!

edit: I'm looking for a workaround so that I can print sin(some multiple of Pi) as a nice round number to the console (ideally without a thousand if-statements)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

我三岁 2024-09-05 14:59:18

每个计算机科学家都应该了解浮点运算(编辑:也在评论中链接)是相当硬核的阅读(我不能声称已阅读全部内容),但其关键在于:您永远无法获得完全准确的浮点计算。来自文章:

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

不要让您的程序依赖于浮点计算的精确结果 - 始终允许一个容差范围。 FYI 3.58979e-009 约为 0.0000000036。这完全在您选择的任何合理的容忍范围内!

What Every Computer Scientist Should Know About Floating-Point Arithmetic (edit: also got linked in a comment) is pretty hardcore reading (I can't claim to have read all of it), but the crux of it is this: you'll never get perfectly accurate floating point calculations. From the article:

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation.

Don't let your program depend on exact results from floating point calculations - always allow a tolerance range. FYI 3.58979e-009 is about 0.0000000036. That's well within any reasonable tolerance range you choose!

蓝天 2024-09-05 14:59:18

这么说吧,3.58979e-009 与 0 非常接近,就像您的 3.14159265 值与真实 Pi 的值一样。从技术上讲,你得到的就是你所要求的。 :)

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

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

Let's put it this way, 3.58979e-009 is as close to 0 as your 3.14159265 value is to the real Pi. What you got is, technically, what you asked for. :)

Now, if you only put 9 significant figures (8 decimal places) in, then instruct the output to also display no more, i.e. use:

cout.precision(8);
cout << sin(Pi);
滥情哥ㄟ 2024-09-05 14:59:18

如果您的相等运算符有足够的容差,则它等于零

it's equal to zero if your equality operator has enough tolerance

苏辞 2024-09-05 14:59:18

您是否尝试过大多数 实现中提供的 M_PI?

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

Did you try M_PI, available in most <cmath> or <math.h> implementations?

Even so, using floating point in this way will always introduce a certain amount of error.

む无字情书 2024-09-05 14:59:18

这应该显示零:(

cout << fixed << sin(Pi);

我认为您不应该尝试舍入任何内容。如果您担心显示,请处理显示函数,而不是值本身。)

This should display zero:

cout << fixed << sin(Pi);

(I don't think you should be trying to round anything. If you are worried about display, deal with the display functions, not with the value itself.)

久光 2024-09-05 14:59:18

3.58979e-009 这是 0,0000000358979

是一个像你的 ~~0 一样的 ~~PI。

3.58979e-009 this is 0,0000000358979

Is a ~~0 like yours ~~PI.

野却迷人 2024-09-05 14:59:18

您可以输入更多数字以获得更好的结果(例如尝试 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 倍数。

You could throw in some more digits to get a better result (try for example 3.1415926535897932384626433832795029L), but you'll still get rounding errors.

Still, you can create your own sin and cos versions that check against your known Pi value and return exactly zero in those cases.

namespace TrigExt
{
    const double PI = 3.14159265358979323846;

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

You may also expand this thing for the other trigonometric functions and to handle Pi multiples.

下壹個目標 2024-09-05 14:59:18

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

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

正如其他人指出的那样,浮点数学是出了名的不精确。如果您希望某些内容完全为零,则需要某种容差。

You could write a little wrapper function:

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

As others have noted, floating-point maths is notoriously inexact. You need some kind of tolerance if you want something to appear as exactly zero.

深海夜未眠 2024-09-05 14:59:18

为什么不强制输入您需要的任意数字

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

why not force to however many digits you need

 int isin = (int)(sin(val) * 1000);
 cout << (isin/1000.0)
淡淡離愁欲言轉身 2024-09-05 14:59:18

对于 PI 的精确值,sin(PI) 应等于 0。您没有输入 PI 的准确值。正如其他人指出的那样,四舍五入到小数点后 7 位的结果是 0,这对于您的近似值来说非常好。

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

sin(PI) should equal 0, for an exact value of PI. You are not entering the exact value of PI. As other people are pointing out, the result you are getting rounded to 7 decimal places is 0, which is pretty good for your approximation.

If you need different behavior you should write your own sine function.

东走西顾 2024-09-05 14:59:18

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

此外,float 和 double 至少在某些编译器和平台上是 64 位。 (我认为 - 如果需要的话有人会纠正我)。对于非常大的值或非常小的值(0.0000000000xxx),这将导致一些舍入错误。

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

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

If you use float or double in math operations you will never have exact results.
The reason is that in a computer everything is stored as a power of 2. This does not translate exactly to our decimal number system. (An example is that there is n o representation in base 2 of 0.1)

In addition float and double are 64 bits at least on some compilers and platforms. (I think - somebody correct me on that if needed). This will cause some rounding errors for either very large values or for very small values (0.0000000000xxx)

In order to get exact results you are going to need some big integer library.

As written in the comments to the question above see the site ...
http://docs.sun.com/source/806-3568/ncg_goldberg.html

谷夏 2024-09-05 14:59:18
double cut(double value, double cutoff=1e-7) {
  return (abs(value) > cutoff)*value;
}

这会将值归零到阈值以下,像这样使用它 cut(sin(Pi))

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

this will zero values below threshold, use it like this cut(sin(Pi))

独守阴晴ぅ圆缺 2024-09-05 14:59:18

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

More significant figures might help. My C compiler (gcc) uses the constant 3.14159265358979323846 for M_PI in "math.h". Other than that, there aren't many options. Creating your own function to validate the answer (as described in another answer to your question) is probably the best idea.

别忘他 2024-09-05 14:59:18

你知道,只是为了数学上的正确性:sin(3.14159265) inst 零。它大约为零,这正是程序告诉您的。对于计算来说,这个数字应该会给你一个很好的结果。对于显示来说,它很糟糕,所以每当您打印浮点数时,请确保格式化数字。

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

不过,关于代码,请小心...通过在显示之前进行近似,不会使您的代码给出错误的结果,只需以正确的方式显示信息即可。

You know, just for the mathematical correctness out there: sin(3.14159265) ins't zero. It's approximately zero, which is exactly what the program is telling you. For calculations, this number ought to give you a good result. For displaying, it sucks, so whenever you print a float, make sure to format the number.

I don't really think that there are any float mechanics in the work here... it's just simple math.

About the code though, be careful... doesn't make your code give the wrong result by making the approximations before the display, just display the information the right way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文