2009-09-21 3 views
2

Мне нужно рассчитать значение tg дуги из моего приложения Blackberry Java. К сожалению, ежевика 4.2 api не имеет функции Math.atan(). Небеса знают, почему, но это Blackberry API для вас. Версия 4.6 Blackberry JDE имеет это, но не 4.2.Вызов функции atan на Blackberry 4.2 JDE

Кто-нибудь знает обходное решение для вычисления atan?

+0

из чистого любопытства, почему вам нужно Atan()? – Calyth

+0

@Dave Причина, по которой функция не существует, заключается в том, что BlackBerry Java начинается с J2ME, а не с J2SE, что и ожидалось бы в мобильном пространстве. J2ME по-прежнему не имеет реализации Math.atan(). – Fostah

ответ

2

Когда все остальное не удается, можно было бы получить приличное значение, оценив результат бесконечной серии функции arctan.

В Wikipedia page on inverse trigonometic functions имеется раздел об инверсных тригонометрических функциях infinite series, включая arctan. Чтобы получить оценку, можно было бы провести бесконечный ряд до тех пор, пока не будет получена желаемая точность.

По причине, почему функция arctan не включена, возможно, это связано с тем, что процессор в Blackberry не очень мощный и потребует много ресурсов процессора для выполнения расчета.

Кроме того, глядя на документацию API Blackberry JDE 4.2 API, похоже, имеется математическая библиотека с фиксированной точкой, называемая Fixed32, которая предлагает два аромата arctan. Они выполняют вычисления с 32-битными целыми числами, поэтому они, вероятно, предлагают некоторые преимущества в производительности по сравнению с арифметикой с плавающей запятой.

3

От 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; 
    } 
} 
1

Вот функция Я не использую (никаких гарантий, что это очень быстро):

/** 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; 
}  
0

Сначала осуществить стандартную arctan(x) используя ряд Тейлора (как описано в http://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Infinite_series)

Перед тем как позвонить arctan, выполните следующие действия:

1) Сначала сделайте эту проверку.

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

2), если |x| > 1, вычислить arctan(1/x) и, наконец, вычесть результат из Pi/2

3), если |x| близка к 1, вычислить арктангенс от половины угла, используя половину угла формулу arctan(x) = 2*arctan(x/(1+sqrt(1+x*x))). То есть сначала вычислите половинный угол, а затем умножьте результат на 2. В противном случае для |x|, близкого к 1, arctan сходится очень медленно.

Смежные вопросы