Hey, guys!
I just recently started working on a project involving a lot of angles and vector math, but I seem to have hit a pretty nasty bump in the road...
It has to do with the standard 'sin' and 'cos' functions in 'math.h', and that they sometimes return really funky values.
Look here, this is a short program I've put together that reproduces the funkiness:
1 | #include <iostream> |
2 | #include <math.h> |
3 | |
4 | using namespace std; |
5 | |
6 | int main() { |
7 | const float PI = 3.14159265f; |
8 | |
9 | cout << "acos(1.0) = " << acos(1.0f) << "\n"; |
10 | cout << "acos(0.0) = " << acos(0.0f) << "\n"; |
11 | cout << "acos(-1.0) = " << acos(-1.0f) << "\n"; |
12 | cout << "\n"; |
13 | cout << "cos(0.0) = " << cos(0.0f) << "\n"; |
14 | cout << "cos(PI) = " << cos(PI) << "\n"; |
15 | cout << "cos(-PI) = " << cos(-PI) << "\n"; |
16 | cout << "cos(PI/2) = " << cos(PI/2.0f) << "\n"; |
17 | cout << "cos(-PI/2) = " << cos(-PI/2.0f) << "\n"; |
18 | cout << "\n"; |
19 | cout << "sin(0.0) = " << sin(0.0f) << "\n"; |
20 | cout << "sin(PI) = " << sin(PI) << "\n"; |
21 | cout << "sin(-PI) = " << sin(-PI) << "\n"; |
22 | cout << "sin(PI/2) = " << sin(PI/2.0f) << "\n"; |
23 | cout << "sin(-PI/2) = " << sin(-PI/2.0f) << "\n"; |
24 | cout << "\n"; |
25 | |
26 | system("PAUSE"); |
27 | return EXIT_SUCCESS; |
28 | } |
And when compiled, on my machine, it gives:
acos(1.0) = 0
acos(0.0) = 1.5708
acos(-1.0) = 3.14159
cos(0.0) = 1
cos(PI) = -1
cos(-PI) = -1
cos(PI/2) = -4.37114e-08
cos(-PI/2) = -4.37114e-08
sin(0.0) = 0
sin(PI) = -8.74228e-08
sin(-PI) = 8.74228e-08
sin(PI/2) = 1
sin(-PI/2) = -1
You can see here that 'acos' works perfectly, but some of the return values from 'sin' and 'cos' look, outright, wrong!
More specifically, cos(PI/2) and cos(-PI/2) should return 0.0, right? And cos(-PI) should return positive 1.0, not negative.
Same thing with 'sin', 'cause sin(PI) and sin(-PI) should also return 0.0, shouldn't they?
Hmmm... I just now realised that even THAT's not right, because typically 0.0 degrees is straight to the right, and 'cos' gives the y-axis and 'sin' the x-axis. If I'm not mistaken.
Oh, well. I'm at a loss, here. Any help is greatly appreciated!
The outputs look fine to me, but you have it backwards: cos gives the x-axis and sin gives the y axis.
cos(PI/2) and sin(PI) should return 0, but there's probably some inaccuracy due to floats not being able to exactly represent pi/2 (and also because your PI is just 9 digits long - try it again using Allegro's AL_PI or M_PI from math.h). So, because of that, you get something very close to 0, but not quite.
Ah, thanks.
I get the same results with M_PI, but what you're saying then is basically that -4.37114e-08 is actually just a really low number, like -0.0000000437... or something?
Remember that
And those other non-zero but approximately zero numbers are sadly just rounding errors. Software probably uses a modified taylor series to calculate it but obviously it doesn't calculate all infinite terms.
acos(-1.0) = 3.14159
...is more off the right value than...
cos(PI/2) = -4.37114e-08
Mmm, then it was all just a matter of inaccuracy. It should still be accurate enough though, for the purposes of my project.
Remember that pi = -pi + 2pi
Yes, it looks obvious enough, but I guess I actually didn't really think about that. I'm not used to working with radians, and I was still thinking of it like degrees. Starting at 0 and going around clockwise to 360.
But, radians then, start at pi going counter-clockwise, full circle, to -pi.
That IS an important thing to remember.
Thanks for the help
EDIT:
Or... Maybe it's not counter-clockwise, I don't know. My point is that to make a full circle with radians, you would start at PI, straight to the left, go around to 0, straight to the right, and then on to -PI.
I think you should look at this
http://en.wikipedia.org/wiki/Unit_circle
..but bear in mind that mathematicians have y going up the page, while us computer people have it going down the screen.
mathematicians have y going up the page, while us computer people have it going down the screen.
To clarify, programmers were used to starting text at the upper right corner of the screen (as is normal) and continuing across, then going to the next line down. When they started fiddling with bitmap graphics, they continued the practice because they were used to it. Mathmaticians usually refer to the 1st quadrant as it has x and y positive, so y=0 is at the bottom.
[EDIT] As pointed out below, start at upper left Doh!
To clarify, programmers were used to starting text at the upper right corner of the screen (as is normal) and continuing across, then going to the next line down. When they started fiddling with bitmap graphics, they continued the practice because they were used to it. Mathmaticians usually refer to the 1st quadrant as it has x and y positive, so y=0 is at the bottom.
Isn't that the upper left corner?
Ah, thanks.
I get the same results with M_PI, but what you're saying then is basically that -4.37114e-08 is actually just a really low number, like -0.0000000437... or something?
Yes. That's exactly what -4.37114e-08 is. The "e-08" notation thing at the end means "times ten to the power of negative 8. So it is exactly what you said.
-4.37114×10⁻⁸
Unicode FTW ✌☺✌
My point is that to make a full circle with radians, you would start at PI, straight to the left, go around to 0, straight to the right, and then on to -PI.
1) When using radians, x = x + 2*Pi*k. So -Pi is equal to Pi which is equal to 3*Pi.
2) You can start wherever the hell you like (remember, a circle has no start nor an end), however for mathematical reasons it is usually more comfortable to use the range [-Pi,Pi].
3) The way you describe this doesn't make sense to me.