3

Is it guaranteed by the C++ standard that angle == std::acos(std::cos(angle)) if angle is in the range [0, Pi], or in other words is it possible to restore the exact original value of angle from the result of std::cos using std::acos given the mentioned range limit?

The marginal cases when angle is infinity or NaN are omitted.

plasmacel
  • 8,183
  • 7
  • 53
  • 101

4 Answers4

3

Answer by StoryTeller:

The standard cannot make that guarantee, simply because the result of std::cos may not be representable exactly by a double, so you get a truncation error, which will affect the result of std::acos.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Is that actually the reason? Is it impossible to make a conforming implementation that would map the value back to the initial value? – xaxxon Oct 15 '16 at 16:03
  • @StoryTeller: If it's a dupe then okay don't answer, but if you _are_ going to answer, please do so in the proper place! – Lightness Races in Orbit Oct 15 '16 at 16:07
  • @xaxxon, I'm afraid not. When the function accepts a value, it must treat every digit as significant, and the value as exactly what the caller intended to pass. – StoryTeller - Unslander Monica Oct 15 '16 at 16:07
  • as defined here in 7.3.5.1 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf – xaxxon Oct 15 '16 at 16:07
  • Did anyone check domains and co-domains? I think the case of approximate roundtrip is of practical interest, while the case of exact result (currently the focus of this answer) is of no practical utility. Not downvoting since it isn't wrong, but it's not relevant either. – Cheers and hth. - Alf Oct 15 '16 at 16:07
  • @LightnessRacesinOrbit, I really hate having to type an answer just to have the question closed in an instant. This comment is just my two cents. – StoryTeller - Unslander Monica Oct 15 '16 at 16:08
  • @Cheersandhth.-Alf, Well it's relevant if the OP wants to rely on `angle == std::acos(std::cos(angle))` always being true, which is of course impossible. – StoryTeller - Unslander Monica Oct 15 '16 at 16:11
3

From cppreference.com:

If no errors occur, [acos returns] the arc cosine of arg (arccos(arg)) in the range [0 ; π]

In degrees, that's 0 to 180, inclusive, corresponding to cosine values 1 down through -1, inclusive.

Outside that range you can't even get an approximate correspondence. Computing the cosine discards information about which angle you had outside of that range. There's no way to get that information back.

How information is discarded:

First, in degrees, cos(x) = cos(K*360 + x), for arbitrary integer K. Secondly, cos(x) = cos(-x). This adds up to an awful lot of angle values that produce the same cosine value.

Also, even though all readers likely know this, but for completeness: since sines are cosines are very irrational numbers, generally not simple fractions, you can't expect exact results except for maybe cosine 1, which corresponds to 0 degrees.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • @xaxxon: pi is little bit irrational, but not much, because it becomes a very systematic, simple sequence of digits when expressed in the factorial numeral system. But the sine of 1.234 degrees, uh oh, that's *very* irrational. :-p – Cheers and hth. - Alf Oct 15 '16 at 16:24
1

According to the standard:

This International Standard imposes no requirements on the accuracy of floating-point operations; see also 18.3.2. — end note ]

http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4606.pdf

xaxxon
  • 19,189
  • 5
  • 50
  • 80
  • True, but the reason is to avoid constraining the implementation from using the full power of the hardware. And I think it's irrelevant. Even *if* a machine existed that could do exact computations every time, the standard cannot make that promise. From a practical standpoint, one should always be careful when dealing with numeric code. – StoryTeller - Unslander Monica Oct 15 '16 at 16:28
  • @StoryTeller The question specifically asked if the standard made the guarantee and I think this bit in the standard very specifically precludes the guarantee which is why I added it as an answer -- because I think approaches the answer from the direction requested in the question. – xaxxon Oct 15 '16 at 16:29
  • I think it's a bit of stretch reading that from this quote. The standard usually tries to be as little limiting as possible. But yeah, I can see why it *could* preclude it. – StoryTeller - Unslander Monica Oct 15 '16 at 16:31
  • @StoryTeller It precludes the standard making the guarantee because they would be mutually exclusive. I wasn't trying to say it precludes an implementation that does so -- but that's not the question posed. – xaxxon Oct 15 '16 at 16:32
  • I see. A rare occasion when a negative claim is provable :) – StoryTeller - Unslander Monica Oct 15 '16 at 16:33
  • @StoryTeller Well, you can just rephrase it. Does the standard allow for sin(asin(x)) != x. Yes. – xaxxon Oct 15 '16 at 16:34
0

Even mathematically this is impossible. For example, cos(2*PI) is 0, but so is cos(4*PI).

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268