在c++中,sin(M_PI)不是0,我怎么解决这个问题呢?

时间:2022-04-20 20:57:21

In C++,

在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?)

我知道这是因为Pi是近似的,但是有什么方法可以让Pi硬编码到我的程序中,它会返回0的sin(Pi)?(不同的常数也许?)

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")

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

The lines that require sin and cosine are:

需要sin和cos的直线是:

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

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

BTW:我的长方形>极坐标工作得很好……它就是->矩形。

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)

编辑:我正在寻找一个解决方案,这样我就可以将sin(Pi)的一个整数打印到控制台(理想情况下不需要一千个if语句)

14 个解决方案

#1


28  

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!

不要让你的程序依赖于浮点运算的精确结果——总是允许一个公差范围。FYI 3.58979e-009约0.0000000036。在任何合理的容忍范围内,你都可以选择!

#2


15  

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. :)

让我们这么说吧,3。58979e-009接近0,因为你的3。14159265的值是实数。从技术上讲,你得到的是你想要的。:)

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

现在,如果你只放9个重要的数字(8位小数),然后指示输出也不再显示,即使用:

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

#3


4  

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

你是否尝试过M_PI,在大多数 实现? 。h>

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

即使如此,用这种方法使用浮点数总是会引入一定数量的错误。

#4


4  

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.)

)我认为你不应该试图回避任何事情。如果您担心显示,请处理显示函数,而不是值本身。

#5


3  

3.58979e-009 this is 0,0000000358979

3.58979 e - 009这是0,0000000358979

Is a ~~0 like yours ~~PI.

和你的一样~~ ~~

#6


3  

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

如果等式运算符有足够的公差,它等于零。

#7


2  

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

你可以用更多的数字来得到一个更好的结果(例如,例如3.1415926535897932384626433832795029L),但是你仍然会得到舍入误差。

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

不过,您可以创建自己的sin和cos版本,这些版本会检查您已知的Pi值,并且在这些情况下返回完全为零。

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.

你也可以把它扩展到其他三角函数中来处理Pi的倍数。

#8


1  

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.

正如其他人所指出的,浮点数学是出了名的不精确。你需要某种公差,如果你想让某些东西看起来正好是零。

#9


1  

why not force to however many digits you need

为什么不强制使用你需要的数字呢?

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

#10


1  

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.

sin(PI)应该等于0,它的精确值是。你没有输入的确切值。正如其他人指出的那样,你得到四舍五入到小数点后的结果是0,这对你的近似值很有好处。

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

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

#11


0  

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)

如果你在数学运算中使用float或double,你将永远不会得到确切的结果。原因是,在计算机中,所有东西都存储为2的幂。这不能精确地转化为我们的十进制数系统。(一个例子是,在0。1的基础上有n o表示)

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)

此外,float和double是64位,至少在一些编译器和平台上。(我想,如果需要的话,有人会纠正我)。这将导致一些非常大的值或非常小的值的舍入误差(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

如上述问题的评论所写,请查看该网站……http://docs.sun.com/source/806-3568/ncg_goldberg.html

#12


0  

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))

这将在阈值以下为零值,像这样使用它(sin(Pi))

#13


-1  

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.

更重要的数据可能会有所帮助。我的C编译器(gcc)在“math.h”中使用了常量3.14159265358979323846。除此之外,没有太多的选择。创建自己的函数来验证答案(正如在另一个答案中所描述的那样)可能是最好的方法。

#14


-1  

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.

你知道,仅仅为了数学的正确性:sin(3.14159265)不等于零。它几乎是零,这正是程序告诉你的。对于计算,这个数字应该会给你一个好的结果。对于显示,它很糟糕,所以每当你打印一个浮点数,一定要格式化数字。

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.

关于代码,请小心……不要让你的代码在显示前做近似,只显示正确的信息。

#1


28  

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!

不要让你的程序依赖于浮点运算的精确结果——总是允许一个公差范围。FYI 3.58979e-009约0.0000000036。在任何合理的容忍范围内,你都可以选择!

#2


15  

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. :)

让我们这么说吧,3。58979e-009接近0,因为你的3。14159265的值是实数。从技术上讲,你得到的是你想要的。:)

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

现在,如果你只放9个重要的数字(8位小数),然后指示输出也不再显示,即使用:

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

#3


4  

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

你是否尝试过M_PI,在大多数 实现? 。h>

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

即使如此,用这种方法使用浮点数总是会引入一定数量的错误。

#4


4  

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.)

)我认为你不应该试图回避任何事情。如果您担心显示,请处理显示函数,而不是值本身。

#5


3  

3.58979e-009 this is 0,0000000358979

3.58979 e - 009这是0,0000000358979

Is a ~~0 like yours ~~PI.

和你的一样~~ ~~

#6


3  

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

如果等式运算符有足够的公差,它等于零。

#7


2  

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

你可以用更多的数字来得到一个更好的结果(例如,例如3.1415926535897932384626433832795029L),但是你仍然会得到舍入误差。

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

不过,您可以创建自己的sin和cos版本,这些版本会检查您已知的Pi值,并且在这些情况下返回完全为零。

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.

你也可以把它扩展到其他三角函数中来处理Pi的倍数。

#8


1  

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.

正如其他人所指出的,浮点数学是出了名的不精确。你需要某种公差,如果你想让某些东西看起来正好是零。

#9


1  

why not force to however many digits you need

为什么不强制使用你需要的数字呢?

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

#10


1  

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.

sin(PI)应该等于0,它的精确值是。你没有输入的确切值。正如其他人指出的那样,你得到四舍五入到小数点后的结果是0,这对你的近似值很有好处。

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

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

#11


0  

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)

如果你在数学运算中使用float或double,你将永远不会得到确切的结果。原因是,在计算机中,所有东西都存储为2的幂。这不能精确地转化为我们的十进制数系统。(一个例子是,在0。1的基础上有n o表示)

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)

此外,float和double是64位,至少在一些编译器和平台上。(我想,如果需要的话,有人会纠正我)。这将导致一些非常大的值或非常小的值的舍入误差(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

如上述问题的评论所写,请查看该网站……http://docs.sun.com/source/806-3568/ncg_goldberg.html

#12


0  

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))

这将在阈值以下为零值,像这样使用它(sin(Pi))

#13


-1  

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.

更重要的数据可能会有所帮助。我的C编译器(gcc)在“math.h”中使用了常量3.14159265358979323846。除此之外,没有太多的选择。创建自己的函数来验证答案(正如在另一个答案中所描述的那样)可能是最好的方法。

#14


-1  

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.

你知道,仅仅为了数学的正确性:sin(3.14159265)不等于零。它几乎是零,这正是程序告诉你的。对于计算,这个数字应该会给你一个好的结果。对于显示,它很糟糕,所以每当你打印一个浮点数,一定要格式化数字。

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.

关于代码,请小心……不要让你的代码在显示前做近似,只显示正确的信息。