views:

568

answers:

4

Hi there. I need to calculate the arc tan value from my Blackberry Java app. Unfortunately, the blackberry 4.2 api doesn't have the Math.atan() function. Heaven knows why, but that's the Blackberry API for you. Version 4.6 of the Blackberry JDE has it, but not 4.2.

Does anyone know of a workaround to calculate atan?

+1  A: 

When all else fails, one could probably obtain a decent value by estimating the result of an infinite series of the arctan function.

The Wikipedia page on inverse trigonometic functions has a section on the infinite series of inverse trigonometric functions, including arctan. In order to obtain an estimate, one would carry out the infinite series until the desired precision is obtained.

As for the reason why the arctan function is not included, it is probably because the processor in the Blackberry isn't very powerful, and would take a lot of processor resources to perform the calculation.

Also, looking at the Blackberry JDE 4.2 API documentation, there appears to be a fixed-point math library called Fixed32 which offers two flavors of arctan. They perform the calculation with 32-bit integers, so they probably offer some performance advantages over performing floating-point arithmetic.

coobird
+3  A: 

From Arctan in J2ME by Stephen Zimmerman:

// calculation functions
public class Calculation {

    // Because J2ME has no floating point numbers,
    // some sort of fixed point math is required.
    // My implementation is simply to shift 10 places.
    // for example, 1024 (>> 10) = 1
    // and 512 (>> 10) = 0.5


public static final int[] AtanTable = { 0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 12,
      13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 
      30, 30,31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 40, 41, 
      42, 43, 43, 44, 45 };

    // / returns angle 0->359 in degrees
    public static int atan(int Y, int X) {
     boolean swap = false;

     int top = Math.abs(Y);
     int bottom = Math.abs(X);
     if (top > bottom) {
      int btemp = bottom;
      bottom = top;
      top = btemp;
      swap = true;
     } else if (bottom == 0)
      return -300;

     // this should keep index inbounds [0, 45]
     int index = (top * 45) / bottom;
     int angle = AtanTable[index];

     if (swap)
      angle = 90 - angle;

     // X & Y += 180
     // X & !Y = ...90
     // !X & Y = ... 270
     if ((X < 0) && (Y < 0))
      angle += 180;
     else if (Y < 0) {
      angle = 90 - angle;
      angle += 270;
     } else if (X < 0) {
      angle = 90 - angle;
      angle += 90;
     }

     if (angle == 360)
      angle = 0;

     return angle;
    }
}
Max Gontar
+1  A: 

Here is the function I use (no guarantees that it is very fast):

/** Square root from 3 */
final static public double SQRT3 = 1.732050807568877294;

static public double atan(double x)
{
    boolean signChange=false;
    boolean Invert=false;
    int sp=0;
    double x2, a;
    // check up the sign change
    if(x<0.)
    {
        x=-x;
        signChange=true;
    }
    // check up the invertation
    if(x>1.)
    {
        x=1/x;
        Invert=true;
    }
    // process shrinking the domain until x<PI/12
    while(x>Math.PI/12)
    {
        sp++;
        a=x+SQRT3;
        a=1/a;
        x=x*SQRT3;
        x=x-1;
        x=x*a;
    }
    // calculation core
    x2=x*x;
    a=x2+1.4087812;
    a=0.55913709/a;
    a=a+0.60310579;
    a=a-(x2*0.05160454);
    a=a*x;
    // process until sp=0
    while(sp>0)
    {
        a=a+Math.PI/6;
        sp--;
    }
    // invertation took place
    if(Invert) a=Math.PI/2-a;
    // sign change took place
    if(signChange) a=-a;
    //
    return a;
}
irlennard
A: 

First implement the standard arctan(x) using Taylor series (as described at http://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Infinite_series)

The do the following before calling arctan:

1) First do this check.

  if (x == 0) {
    return 0;        
  }

2) if |x| > 1, compute arctan(1/x) and finally subtract the result from Pi/2

3) if |x| is close to 1, compute arctan of the half angle using the half angle formula arctan(x) = 2*arctan(x/(1+sqrt(1+x*x))). That is, first compute the half angle and then multiply the result by 2. Otherwise, for |x| close to 1, arctan converges very slowly.

Jus12