I'm trying to do some work with some simple trigonometric functions. (Law of Sines and Cosines knowledge is useful here) I have a triangle:
__
\ /
\/
(I apologize for the crudity of this triangle!)
To label, the top side is c, and the other two sides are a and b. The top-left angle is A, the top-right angle is B, and the other is C.
The angle measure of C is 45°, and its opposite side c is unknown. The other two sides are 2.0 units in length. From that I know that the other angles are going to be 67.5°. The problem that occurs is if I try to do this in C++ I know that c = 1.53073... but if I try to calculate angle A or B, the answer will always come out as 67.500008° I know that the angle measure of these are really 67.5°.
I calculate it this way:
1 2 3
c = sqrt(pow(a, 2.0f) + pow(b, 2.0f) - 2.0f*a*b*cosf(C * PI/180.0f));
A = asinf((a*sinf(C * PI/180.0f))/c) * 180.0f/PI;
B = asinf((b*sinf(C * PI/180.0f))/c) * 180.0f/PI;
The PI/180 and 180/PI are necessary because the functions do the calculation in radians. And PI is just some constant float I made of 3.14159265358979... and clearly that is just an estimation of PI.
What I want to know is how do I calculate it so that the angle measure of A and B will be 100% accurate?
The reason the angle is being calculated as 67.5000008^{o} has to do with how the computer calculates and handles floating point variables. There are often awkward rounding errors when you use floats depending on how they're truncated, and varies depending on compiler, optimizations, and architecture.
for example
1 2 3 4 5 6 7 8
#include <iostream>
usingnamespace std;
int main()
{
cout << setprecision(17);
double value = 0.1;
cout << value << endl;
}
You would expect this code to output 0.1, but it actually outputs something like
0.10000000000000001
This is why you can never use equality comparisons on floats. You can only compare them accurately with inequality operators.
These errors can wreak havoc on math intense programs, and as far as i'm aware there's little you can do to avoid them when using floating point variables.
Calculations are hardly ever 100% accurate. However, if it's important that your program avoids these, you should have a look into fixed point arithmetic. There are some third party libraries that implement them well. http://code.google.com/p/libfixmath/ Check this link out.
In addition to what Thumper said, you could use doubles (they are good for 15 significant figures) rather than floats (8 sf) for all your variables, then cout them with 6 decimal places say. This ought to give reasonable results.
The other thing to do is to calculate the value of PI/180.0 & 180.0/PI and use them as constant variables so the program doesn't have to calc them each time.
Ah, I've just always used floats, I used doubles when I first started out with C++ learning what everything is, but ever since then I've always used floats as it's practically all I see, even in OpenGL applications. I got it by using scanf with %lf and printf with %g. It made so much simpler.
And as for the PI/180.0 and 180.0/PI I did that for the sake of time because I wasn't making some big program, I just used it to make a program so I could find out two unknown angles and the one unknown side of a triangle in a simple way.