-1

I'm using the asin and acos functions from cmath library to find the angles from their corresponding sine and cosine values but it sometimes returns inaccurate values. For example the result of the code below is not zero:

cout << acos(-1) / 6 - asin(0.5) << endl;

So what can I do? I use acos(-1) as the value of Pi, then somewhere in my code I want to see for example how many asin(0.5) are there in Pi but current method doesn't work.

therealak12
  • 1,178
  • 2
  • 12
  • 26
  • 2
    Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – François Andrieux Sep 09 '19 at 19:11
  • @FrançoisAndrieux The context is the same, but I posted this mostly because of the solution. I have tried the solutions in that post, e.g., rounding but they didn't work as I expected. My code had to pass several tests and just the method I mentioned below worked in all the tests, using other solutions my code wasn't able to pass all the tests. – therealak12 Sep 10 '19 at 08:03
  • AK 12, "the result of the code below is not zero" --> what was the result you saw? – chux - Reinstate Monica Sep 10 '19 at 14:56
  • AK 12, "but current method doesn't work" --> If you need help with the method, post the code. – chux - Reinstate Monica Sep 10 '19 at 14:57
  • There's an example of how to implement an `almost_equal` function here: [std::numeric_limits::epsilon](https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon) – Ted Lyngmo Sep 10 '19 at 14:59

1 Answers1

0
  • Inexactness lurks in various places.

double is very commonly encoded using base 2, such as with binary64. As a floating point number, it can be expected to be a Dyadic rational. The key is that a finite floating-point number is a rational number.

Mathematically, arccos(-1) is π. π is an irrational number. Even with many digits of precision, a double cannot represent exactly π. Instead a nearby value for acos(-1) is used called machine pi or perhaps M_PI.

Mathematically, arcsin(0.5) is π/6. As above, asin(0.5) is a nearby value to π/6.

Division by 3 introduces potential inexactness. About 2 of every double/3 results in an inexact, yet rounded, quotient.

  • Of course it is not zero.

What is curious about this is that acos(-1) / 3 - asin(0.5) is about 1.57..., not 0.0.

I suspect OP was researching acos(-1) / 6 - asin(0.5).

Here subtraction of nearby values incurs catastrophic cancellation and a small, but non-zero difference, is a likely outcome.


So what can I do?
I want to see for example how many asin(0.5) are there in Pi

Tolerate marginal error in the calculation and employ the desired rounding.

double my_pi = acos(-1);
double target = asin(0.5);
long close_integer_quotient = lround(my_pi/target);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256