Клас Math

Java Syntax Zero
Рівень 9 , Лекція 1
Відкрита

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() — просто ідеальне рішення.


Коментарі (18)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
ivan Рівень 10
30 липня 2024
Задача про масив злам мені мозок допомогли коментарі...
Гаркін Рівень 14
5 березня 2024
Тут лише я почуваюсь тупеньким, коли розбирав drawValue ? (фіг-вам. Я не розібрав. Бо перемножувати усі ті формули... та ну його...). І це лише мені ось цей рядок був новим

char c = i == N ? '|': '.';
і (м'яко кажучі) не зовсім зрозумілим? (так, через деякий час я зрозумів що то тернарний оператор, і чому тут викорисовується char ... Але) Ну ок...
Гаркін Рівень 14
5 березня 2024
Ох йо… треба відпочивати . Знали б Ви, скільки мені часу знадобилось, щоб розібратись, що рядок double sin(double d) то є метод (який належить до класу Math ) sin , а в дужках double d то є опис параметрів того методу (тобто для його роботи треба вказати d, яке повинно бути дійсним числом, на що і вказує double у дужках). Але є трабл – я не розумію що то за double на початку. Пофіг. Я виконую одне завдання і відпочивати.
Olexandr Рівень 47
17 листопада 2023
Да ладно, рекурсия))) Я выполнил - вручную прописав все десять переменных и их сравнение))) Потом уже посмотрел, как это можно сделать циклом) Задача отличная.
les_yeux_blancs Рівень 50
21 квітня 2023
Імхо, останню задачу варто давати після того, як познайомите учнів з поняттям рекурсії (хоча, можливо, у дефолтному розкладі з нуля ця лекція і іде пісня неї) Ось рішення:

    public static int min(int[] ints) {
        if (ints.length == 2) {
            return Math.min(ints[0], ints[1]);
        }

        return Math.min(ints[0], min(Arrays.copyOfRange(ints, 1, ints.length)));
    }
14 травня 2023
Задачу можна виконати без використання рекурсії
Antek_Ukraine Рівень 14 Expert
28 червня 2023
Навіщо? Проходимо циклом fori по масиву (i=0,i<ints.length(), i++), порівнюючи КОЖНИЙ елемент масиву ints з змінною min (її ініціалізував як Integer.MAX_VALUE) метод повертає ту саму min Прийняло з першого разу
Vitalii Рівень 11
14 серпня 2023
трохи оптимальніше min відпочатку присвоїти значення першого елемента масива.
Ва Дим Рівень 28
23 березня 2024
А мені сподобався спосіб.Не стандартно якось використати метод який ти створюєш в методі яки ти створюєш😁.Я б до такого точно не додумався.
bogdan kravchuk Рівень 11
15 березня 2023
Чомусь цей рівень дуже важкий для мене. поопередні було все зрозуміло це шось взагалі не допетраю...
FAUST_ua Рівень 29
15 липня 2022
майже зломав голову об останню задачу..
Lipovskyi Volodymyr Рівень 36
11 травня 2022
В другій задачі треба закоментувати пів коду, щоб працювало)
shved IT Рівень 26
1 березня 2022
for (int number : ints) { min = Math.min(min, number); } return min; } что значит условие в скобках? для
Me Lex Рівень 12
20 березня 2022
вот и мне интересно но я сделал по своему без подсказки и у меня получилось через (int i = 1 ; i<ints.length; i++)
Olena Рівень 14
5 серпня 2022
foreach цикл идет по каждому вашему элементу массива, происходит присвоение текущего эл-та массива в переменную number и в

min = Math.min(min, number); 
когда передаете number по сути обращаетесь к текущему эл-ту искомого массива int[] ints . Видимо, foreach использовали потому, что у нас нет явной размерности []ints
Roma Chernesh Рівень 16
21 грудня 2022
Щодо for (number : ints) - це цикл foreach. Якщо коротко, то ось два різні спобоба написати одне й теж саме: 1) цикл for: for (int i = 0; i < ints.length; i++) { int number = ints[i] } 2) цикл foreach: for (number:ints) { } Сходу може бути незрозуміло, тому раджку почитати статтю про цей цикл: https://javarush.com/groups/posts/for-each-java
Александр Рівень 12
8 листопада 2021
как все таки правильно: 1) Math.sin(Math.toRadians(a)); или так 2) Math.sin(toRadians(a));
Axis Рівень 12
24 січня 2022
там уже импортирован пакет import static java.lang.Math.toRadians; тобишь - второй вариант