In C++,
cons开发者_如何学运维t 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)
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!
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);
it's equal to zero if your equality operator has enough tolerance
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.
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.)
3.58979e-009 this is 0,0000000358979
Is a ~~0 like yours ~~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.
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.
why not force to however many digits you need
int isin = (int)(sin(val) * 1000);
cout << (isin/1000.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.
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
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))
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.
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.
精彩评论