Trigonometric Rounding errors

I've been trying to create a rotational operator using the rotational matrix R (2x2 matrix).

The elements of this matrix consist of trigonometrical functions, cos and sin from the cmath library, which take the angle in radians as their argument.

Problem is, when I try to input a multiple of pi (taken as acos(1.)) close to a known value, there is a significant rounding error.

For example; cos( pi / 2 ) = cos (90 deg) should equal 0; but the value returned is 6.12323e-17. Which is very close...but not quite right (because the value for Pi is not exact).

I've tried adding a check:
1
2
3
4
5
6
7
8
9
10
	double A = cos(DEG), B = sin(DEG);
	if (A < -0.9999999){A = ceil(A);}
	if (B < -0.9999999){B = ceil(B);}
	if (A > -0.0000001 && A < 0.0000001){A = 0.;}
	if (B > -0.0000001 && B < 0.0000001){B = 0.;}
	if (A > 0.9999999){A = floor(A);}
	if (B > 0.9999999){B = floor(B);}
	cout << "A" << A << endl;
	cout << "B" << B << ",\t-B" << -B << endl;	
	

These I think should round to the nearest key value; but A still returns the value 6.12323e-17 for cos( pi / 2) after this. Surely it should fall into the middle case for A?
When doing floating point arithmetics, errors are something you have to live with. Is there really something wrong with an error of 6*10-17 ? I really doubt that..
Managed to fit a rounding method in in the end.
The reason I wanted to round it up is because I thought it might have been the cause of an error later in the function, but it's looking more like a reference mistake (a value of the order e+66 is returned where a 1 is expected).

So while 6*10-17 is pretty much 0 for this application, and should work, a matrix of
/ 0 1 \
\ -1 0 /
is a lot easier for me to process than:
/ 6.12323*10-17 1 \
\ -1 6.12323*10-17 /

EDIT: Found and fixed the problem causing the e+66 error - rounding is just to clean up the output coordinates, which should be simple enough now using the above code segment
(reason it wasn't working before was I was editing a different class to the one I was testing /facepalm)
Last edited on
Surely you have to process an arbitrary matrix. How does it make it easier if in one particular case the matrix becomes <<0, 1>, <-1, 0>>?
I mistakenly thought a non-zero result would skew a different part of my code.

This rotation works for a number of polygons, but one of the classes (rectangle) has a check to ensure that it is a rectangle (dot product for each pair of consecutive sides, should = 0).

My fear was that after a rotation, because of the non-zero component it would fail the check and not acknowledge that the final result was still a rectangle. This is incorrect though, as the error is consistent for each of the sides.
In fact; including the correction would have messed up the check more than leaving it be.
If you are concerned about equality checks failing due to error, you could do something like this. Replace:
if (double_variable == 0) // etc
with
1
2
3
const double tolerance = <choose some tolerance>;
// etc
if (fabs(double_variable) < tolerance) // etc 

It's not great, but it would work.
Last edited on
Looks like it would work - but given the other features yet to be fixed I think I'll just explain where the error comes from in the comments and documentation.

Thanks everyone!
Topic archived. No new replies allowed.