24 февр. 2012 г.

Приближённые вычисления арктангенса в MIDP 2.0

Как известно, объект java.lang.Math в MIDP 2.0 лишён функции atan(), как впрочем и многих других обратных тригонометрических функций. Однако арктангенс практически незаменим при вычислении значений углов прямоугольного треугольника по известным длинам его катетов. Ниже представлена одна из возможных реализаций функции арктангенса, дающая вполне хорошие результаты для аргументов в самом широком диапазоне. Следует лишь напомнить, что данная функция принимает в качестве аргумента величину отношения противолежащего катета прямоугольного треугольника к прилежащему, и возвращает значение соответствующего угла в радианах.


// Константы, необходимые для вычисления арктангенса
private static final double tanPI12 = Math.tan(Math.PI/12);
private static final double tanPI6 = Math.tan(Math.PI/6);
private static final double PI6 = Math.PI/6;
private static final double PI2 = Math.PI/2;

private static final double c1 = 1.6867629106;
private static final double c2 = 0.4378497304;
private static final double c3 = 1.6867633134;

/**
* Функция приближённого вычисления арктангенса.
*
* @param a Отношение противолежащего катета прямоугольного треугольника к прилежащему
* @return Значение соответствующего угла в радианах
*/
public static double atan(double a)
{
double result = 0;

boolean complement = false; // Принимает значение true если аргумент "a" больше 1.0
boolean region = false; // Принимает значение true если аргумент "a" больше значения Math.tan(Math.PI/12)
boolean sign = false; // Принимает значение true если аргумент "a" отрицательный

if (a < 0)
{
a = -a; // Дать аргументу "а" позитивное значение
sign = true; // Дать результату негативное значение
}

if (a > 1.0)
{
a = 1.0 / a; // Преобразовать аргумент "а" в значение от 0 до 1.0
complement = true;
}

if (a > tanPI12)
{
a = (a - tanPI6) / (1 + tanPI6 * a); // Ограничить аргумент "а" значениями от 0 до Math.tan(Math.PI/12)
region = true;
}

// Вычислить приблизительное значение арктангенса для значения "а" в диапазоне от 0 до Math.PI/12
result = a * (c1 + a * a * c2) / (a * a + c3);

if (region)
{
result += PI6; // Поправить значение угла, так как аргумент имел значение больше Math.tan(Math.PI/12)
}

if (complement)
{
result = PI2 - result; // Поправить значение угла, так как аргумент имел значение больше 1.0
}

if (sign)
{
result =- result; // Поправить значение угла, так как аргумент был негативным
}

return result;
}