cosine/sine extra precision(rounding)

Started by
8 comments, last by Perost 15 years, 4 months ago
I have the following problem, yet i must say i looked (but not to much for the answer, hence i didnt find one). As am trying to get a "dot" moving according to my mouse cursor, my mouse cursor is actually representing an angle inside the window rectangle as the X/Y coords its pointing within the window. Here is my problem, if i get a Right angle (90.0) and am trying to get the cosine value, I convert the 90 into radians = angle_degrees * PI / 180 but the problem is that if i use the data type "float" am getting = 1.5707964, which is cosine is -7.3205103251e-8 and if i use "double" the result is 1.5707963705062866 which leads to cosine -4.3711390002e-8 I am not aware if thats a known problem or rookie mastike, so i didn`t know where to post it, beginner or here. Thanks in advance.
Advertisement
Floating-point numbers have limited precision. They represent some numbers correctly, but the vast majority is just approximated.

For instance, PI/2 is approximated, so you will never be able to store that value in a computer (unless you start using formal representations).
Nice to know, so where does it put me :) ?
Do i need to use another data type?

Or do i need to learn a new approach that avoid that problem?
In 99% of programs, this is not a problem, because the precision is high enough. If your problem needs improved precision, then it must be doing something quite unusual, and the solution will then depend on what exactly the program is doing.

So, why is an error of 4e-8 unacceptable for your program?
What libraries are you using for cosine? If I follow what you are doing in matlab (which uses IEEE double precision floating point; and because I don't want to open my IDE) I get the following
>> pians =   3.141592653589793>> a=90*pi/180a =   1.570796326794897>> cos(a)ans =    6.123233995736766e-017

which is sitting (almost) right on machine epsilon in double precision. As expected.

I'm really surprised that there is NO precision gain by going to double for you. Something seems off. In matlab single() returns the single precision number. Therefore:
>> single(cos(single(90*pi/180)))ans =  -4.3711388e-008

Which is what you get for your "double" precision. Which confirms it.

Are you sure you're
a) using a cos(double d) function?
b) are you sure that any intermediate steps are also using single precision? one always plays to the lowest common denominator.
Quote:Original post by Illasera
Nice to know, so where does it put me :) ?

If you travel at -4.3711390002e-8 miles per hour for a full day, you will find yourself a grand total of 1.6 millimeters from where you started. So, it puts you pretty much where you need to be.
I should have known am out of my league :)

I was looking for a way to get an answer of 0 for a right angle.

I really have no idea what to do with the exponent.

Much apologize for my lack in knowledge.

Basicly what am trying to do is get a displacement on the x Axis with the mouse coords

#include "math.h"#define PI 3.1415926536f#define PIdiv180 PI/180.0ffloat NormalFireAngle(unsigned int ScreenWidth, POINT* MousePos){	float x_pos = (float)MousePos->x; // screen border + mouse pos x on window	float y_pos = 480 - (float)MousePos->y; // offset screen border	float Angle = atan2(y_pos, x_pos);	return (Angle * 180.0f) / PI; // Is referred to "PlayerAngle in the 2nd function};Vector2d NormalFireMode(Vector2d* FirePos, float PlayerAngle){//PlayerAngle is mouse coords from the previous function.	Vector2d temp ;	float velocity = 0.2f;	float Time = 0.016;	temp.m_x = ((cos(PlayerAngle * PIdiv180) * Time) * velocity);	VectorAddition(*FirePos, temp); 	return *FirePos;};


Solved : guess there was nothing wrong, all the big numbers in Debug scared me, thats all
Quote:Original post by Illasera
I should have known am out of my league :)

Nah, it's just what happens when working with computers. It makes sense when you think about it.

Sine and cosine are calculated via series.


As you can see, they sum from 0 to infinity. However, as you computer each term, the effect it has on the answer decreases (because the denominator is always larger than the numerator). Therefore in the computation of the series we can truncate it and still obtain an answer that
a) doesn't take an infinite amount of time to computer and
b) is *almost* right

So right off the bat here we are obtaining an approximation to cosine. At each step of the computation we also experience round off error which is subtly changing the results.

Quote:
I was looking for a way to get an answer of 0 for a right angle.

Unless you do symbolic maths (a la Maple) this isn't going to happen because of
A) round off
B) an approximation to cosine

Quote:
Much apologize for my lack in knowledge.

don't, we are all learning!

In the code you posted, is there a reason you are using single precision?

For what you are doing why is an error of 10^-8 not acceptable?
If you get used to doing operations with vectors, you'll find that often you can avoid using angles, and most of the time that's the best solution. I didn't quite understand what you are doing, but it looks like you are taking the mouse position, converting that to an angle (details missing) and then using that angle to reconstruct some vector that you'll use as velocity for your dot. That sounds like a good example of the kind of things that don't need angles.

If you carefully explain what you are doing and/or you post some code, I can try to help you not use angles.

Quote:Original post by Illasera
I was looking for a way to get an answer of 0 for a right angle.

As the others have told you there will be rounding errors, so you will rarely get exactly 0. Something you can learn from this is that you should never compare with 0 when using floating point numbers. Instead you should compare with a small number that is sufficiently close to 0 for your application. So instead of doing the comparison
f == 0
where f is a float or double, you should do something like
fabs(f) < EPSILON
where fabs is the standard function for getting the absolute value of a float, and EPSILON is a small number close to 0 that depends on what precision you require.

It's not applicable in this case, but it's good to know.

This topic is closed to new replies.

Advertisement