How to calculate rounded trigonometric functions in degrees?

How could I define trigonometric functions that take arguments in degrees instead of regular radians and calculate correctly rounded results for these arguments?

Multiplying the argument by M_PI/180.0 before passing its corresponding function in radians does not work, because M_PI/180.0 not π / 180. Section 5.5 of the Floating Point Arithmetic Handbook offers a method for calculating the correctly rounded product of an argument by π / 180, but some arguments will still be such that this product is close to the middle between two consecutive represented floats, and then applying even a correctly rounded function in radians may lead to an incorrect final result.

Two strategies that can work independently or in combination, use higher accuracy and use the trigonometric functions sinpi , cospi , tanpi from CRlibm , which calculate sin(πx) , cos(πx) and tan(πx) , respectively.

For the latter strategy, the problem of dividing by 180 remains, which is not accurate for many arguments.

As for the strategy with higher accuracy (multiplying the argument by a representation with extended accuracy π / 180, then applying the function of extended accuracy in radians), there may be a problem with “exact” cases. The theorem that the only rational results sin , cos and tan for a rational argument obtained at 0 applicable only to radian versions. Obviously this does not apply to degree versions, and if for some floating-point input x, sindeg (x) is exactly the middle between two consecutive represented floating-point numbers, then the intermediate precision is not enough to ensure that the final result is correctly rounded .

+7
floating-point trigonometry
source share
4 answers

The only rational q for which cosdeg(360q) rational have 1, 2, 3, 4, or 6 as the denominator. This article by Jörg Janel contains a short and beautiful proof using the field theory in Section 6. (Indeed, the author characterizes the degree of the algebraic number cosdeg(360q) using the Euler identity function.) Thus, there is no floating point q , so cosdeg(360q) is halfway between two adjacent floating point numbers.

So, I think the answer is “about the same as you implement sin and friends for radians”, although @ gnasher729 makes a great point that reducing arguments for degrees is much, much nicer.

+3
source share

It's complicated. On the plus side, you can precisely reduce the argument to +/- 45 degrees. Therefore, you need to properly round the results between +/- 45 degrees. For very small x, sin (x) is approximately x * (pi / 180), which is difficult enough to round exactly.

To get basically correctly rounded results for a sinusoidal function, for example, take -45 <= x <= 45. Divide x by xhi = round (512 x) / 512 and xlo = x-xhi. Let sin (x degrees) ≈ ax - bx ^ 3. Round a and b, so that s (x) a * xhi - b * (xhi ^ 3) is calculated exactly. Calculate the remainder sin (x degrees) - s (x) carefully; rounding error should be quite small, because the result is small. Add to s (x), this in most cases will give a correctly rounded result.

+1
source share

Well, that is a tough question. Let me clarify some points:

  • What accuracy is required for output? Is the IEEE 754 single or double precision or non-standard? Moreover, I believe that the input, i.e. The one presented in degrees should be displayed with the same accuracy as the outputs, as is the case for normal radian inputs.
  • What are your performance metrics? CRlibm is optimized for correctly rounded double precision results. MPFR, on the other hand, is used for arbitrary precision, but it is much slower than CRlibm when you only need a double-precision result.
  • What is your working range? those. [min argument, max argmunet]? This is important for CRlibm as it works for double precision ranges. However, for MPFR this does not really matter.

Basically I recommend using MPFR if you are required to use inputs only in degrees. Let me remind you that any argument in degrees, when it is multiplied by (Pi / 180), creates a transcendental number. However, what is transferred to the trigonometric function is a floating point representation rounded, preferably rounded to the nearest integer, to working accuracy.

I recommend you do the following:

  • Use MPFR, use the C library whenever possible, as it provides much better performance than its bindings.
  • Set the accuracy of MPFR much higher than your target accuracy. For example (target accuracy + 300). By doing this, you avoid losing accuracy for the operation ((Argument * Pi) / 180). This can be easily done in the MPFR C library using mpfr_set_default_prec ().
  • Perform the operation: X_n = (Argument * Pi) / 180, and then execute Sin (X_n) or any other function that you want. MPFR has a constant Pi, which is presented in your working accuracy.
  • Rotate the result to the target accuracy.

"Elementary functions," according to Müller, statistically show that most, NOT EVERYTHING, of hard cases are correctly rounded if the operational accuracy is slightly higher than twice the target accuracy. But in your case, since the input is theoretically transcendental, to be safe, at the expense of productivity, to make the working accuracy much higher than the target. In fact, 10x is sufficient for almost 100% of cases if you need the final result with double precision.

If you need low accuracy, that is, single accuracy or lower, you can perform an exhaustive test to solve the lowest working accuracy that ensures that all cases are correctly rounded.

+1
source share

First you need to determine the exact cases, and this has already been answered. Now, for other cases, there is a known problem with the table creator's dilemma. If your arithmetic has fixed (and low) accuracy and you need a certified reference to intermediate accuracy, which may be required, there are two well-known solutions:

  • Get an estimate based on the Nesterenko and Waldschmidt theorem as described in section 4.3 of my doctoral dissertation (BTW, I think this will also give you the form of exact cases). But you get very large boundaries of accuracy (at least a few million bits?).
  • Find a hard case. It is enough to search in [0,180], since any larger argument will decrease to the value in [0,180] with the same fractional part (since the period is an integer).
+1
source share

All Articles