1. Тригонометрические функции в Java

Ранее, когда мы изучали округление чисел, мы познакомились с классом Math и некоторыми его методами. Сейчас мы рассмотрим этот класс более подробно.

В классе Math, на что как бы намекает это название, собраны самые часто употребляемые программистами математические функции. Вот самые интересные из них:

Метод Описание
double sin(double d)
Возвращает синус угла d, заданного в радианах
double cos(double d)
Возвращает косинус угла d, заданного в радианах
double tan(double d)
Возвращает тангенс угла d, заданного в радианах
double asin(double d)
Возвращает арксинус
double acos(double d)
Возвращает арккосинус
double atan(double d)
Возвращает арктангенс
double sinh(double d)
Возвращает гиперболический синус
double cosh(double d)
Возвращает гиперболический косинус
double tanh(double d)
Возвращает гиперболический тангенс

Функции Math.sin(), Math.cos() и Math.tan() принимают угол, заданный в радианах. Чтобы преобразовать углы из градусов в радианы и обратно, в классе Math есть две специальные функции:

Метод Описание
double toRadians(double angdeg)
Преобразует угол из градусов в радианы
double toDegrees(double angrad)
Преобразует угол из радиан в градусы

В классе Math, кстати, есть не только функции, но еще и две переменные-константы (статические поля класса):

Константа Описание
double Math.PI
Число «Пи» равное 3.141592653589793
double Math.E
Число «Е» равное 2.718281828459045

Все эти функции могут быть вам очень полезны, если вы решите писать свои игры, работать с графикой, ну или просто посчитать длину пути по карте.

Например, если вы хотите вычислить sin(45°), вот как можно это сделать:

Math.sin( Math.toRadians(45) )

Пример использования:

public class Main
{
   public static int N = 10;

   public static void drawValue(double y)
   {
     int value = (int) (y * N) + N;
     for (int i = 0; i < 2 * N; i++)
     {
       char c = i == N ? '|': '.';
       if (i == value)
         c = '*';
       System.out.print(c);
     }
     System.out.println();
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10 * N; i++)
     {
       double x = i * 1.0 / N;
       double y = Math.sin(x);
       drawValue(y);
     }
   }
}


2. Алгебраические функции в Java

В большинстве случаев программисту с головой хватает школьной математики: даже синусы и косинусы в коде можно встретить очень редко. Чаще всего они нужны при работе с играми, картами или игровыми движками. 90% программистов с этим никогда не сталкиваются.

Но, кроме геометрии, программистам иногда приходится использовать и алгебраические функции. И, конечно же, класс Math содержит самые распространенные из них:

Метод Описание
double sqrt(double a)
квадратный корень из a
double cbrt(double a)
кубический корень из a
double pow(double a, double b)
возведение в степень: ab
double exp(double a)
экспонента: ea
double log(double a)
натуральный логарифм a: ln(a)
double log10(double a)
десятичный логарифм a: log10a
double log1p(double x)
натуральный логарифм x + 1: ln(x + 1)
double expm1(double x)
ex-1

Если вам нужен квадратный или кубический корень из числа, для этого есть функции sqrt(a) и cbrt(a).

Корень из двух можно вычислить так:

Math.sqrt(2)

Если вы хотите получить корень более высокой степени, воспользуйтесь функцией возведения в степень: a в степени ¼ — это и будет корень четвертой степени, и т.д.

Math.pow(2, 0.25)

Для работы с логарифмами и экспонентами есть функции log(a) – натуральный логарифм и exp(x) — экспонента. Для вычисления десятичного логарифма есть функция log10(a).

Если вам нужен логарифм числа b по основанию a, воспользуйтесь простой формулой: logab = ln(b) / ln(a)

Полезные функции

Последние две функции log1p() и expm1() могут быть вам полезны, если вы проводите вычисления при очень маленьких значениях x.

При сложении очень маленьких и очень больших double переменных часто может возникнуть ситуация, когда очень маленькое значение просто игнорируется (отбрасывается) как незначащее. Это, собственно, и будет происходить, если использовать функции log() и exp(). Поэтому программисты придумали функции, которые возвращают только ту самую «маленькую значащую часть»

Пример:

Вы хотите посчитать натуральный логарифм от 1 + x, где х равен 10-20. Вы просто не сможете передать это число в функцию log(), т.к. если сложить 1 и 10-20, получится 1. 10-20 — настолько маленькое число, что будет отброшено полностью при сложении чисел.

А т.к. в математике часто приходится вычислять log() при числах, близких к 1, программисты придумали способ обойти эту проблему: передать в функцию не само число, а только его отличие от 1.



3. Минимум и максимум

И еще две полезные функции — это функции min(a, b) и max(a, b). Первая, как вы уже, наверное, догадываетесь, возвращает минимум из двух чисел:

Math.min(a, b)

А вторая — максимум из двух чисел:

Math.max(a, b)

Зачем же нужны эти функции, если всегда можно написать if или даже использовать тернарный оператор a < b ? a : b

Все дело в читабельности кода. Иногда код и так перегружен if-ами и хочется использовать более компактную запись. Сравните:

Код Описание
int x = 0;
if (x-5+y*20 < x*x+y*y)
   x = x-5+y*20;
else
   x = x*x+y*y;
Самая длинная запись формулы через if-else
int x = x-5+y*20 < x*x+y*y ? x-5+y*20 : x*x+y*y;
Записать через тернарный оператор. Минусы:
– громоздкий код
– дважды выполняются вычисления
int a = x-5+y*20;
int b = x*x+y*y;
int x = a < b ? a : b;
Хорошая запись, но немного избыточная
int x = Math.min(x-5+y*20, x*x+y*y);
В самый раз 🙂

4. Минимум и максимум из нескольких чисел

Есть еще одно полезное применение функций min() и max().

Это вычисление минимума (или максимума) из нескольких чисел или переменных. Функции очень удобно вызывать друг в друге.

Вот как можно записать минимум из 3-х чисел:

Math.min(a, Math.min(b, c))

А что? Очень удобно: вычисляем минимум пары чисел, а затем возвращаем меньшее число из найденного и оставшегося.

Минимум из четырех чисел получается аналогично:

Math.min(a, Math.min(b, Math.min(с, d)))

Хотя можно эту формулу записать немного понятнее:

Math.min(Math.min(a, b), Math.min(c, d))

Для функции max() все аналогично.

Использование оператора if-else или тернарного оператора сделало бы эти записи немного более громоздкими. А использование функций min() и max() — просто идеальное решение.