JavaRush /Курси /Java Syntax Zero /Лайфхаки: як писати код краще та швидше

Лайфхаки: як писати код краще та швидше

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

1. Вирази vs Команди

Усі команди в Java поділяються на дві категорії: команди (Statement) та вирази (Expression). Про команду зазвичай говорять, що вона виконується, а про вираз — що він обчислюється. Але це не головне.

Основна різниця між командою та виразом у тому, що у виразу є результат обчислення. І у цього результату, по-перше, є тип, а по-друге, цей результат можна кудись присвоїти або використати у якомусь іншому виразі.

Приклади:

Код Примітки
int x; Команда
(a < 10) Вираз, тип boolean
i++; Вираз, тип збігається з типом змінної i
x = 5; Вираз, тип збігається з типом змінної x

І що це нам дає?

По-перше, ми можемо використовувати той факт, що дуже багато команд насправді є виразами (мають результат обчислення). Наприклад, такий код працюватиме:

Код Примітки
int x, y, z;
x = y = z = 1;
int x, y, z;
x = (y = (z = 1));

По-друге, ми можемо ігнорувати результат обчислення виразу, якщо хочемо.

Код Код, де ми ігноруємо результат:
int x = scanner.nextInt();
boolean m = (5 < 10);
scanner.nextInt();
(5 < 10);

Ігнорувати результат обчислення виразу потрібно, наприклад, якщо вираз окрім результату робить ще щось корисне, і нам ця дія важлива, а сам результат — ні.


2. Тернарний оператор

Цей лайфхак вже цікавіший за попередній. У Java є спеціальний тернарний (потрійний) оператор. Він чимось схожий на скорочений запис оператора if–else:

Умова ? Вираз1 : Вираз2;

Якщо умова істинна, то виконується вираз1, інакше виконується вираз2. Після умови йде знак питання, а два вирази розділені двокрапкою.

Основна відмінність тернарного оператора від оператора if-else у тому, що тернарний оператор є виразом, а отже, його результат можна чомусь присвоїти.

Наприклад, ми хочемо обчислити мінімум двох чисел. З використанням тернарного оператора цей код виглядатиме так:

int a = 2;
int b = 3;
int min = a < b ?  a : b;

Або, припустимо, вам потрібно присвоїти змінній різні значення залежно від якоїсь умови. Як це зробити?

Перший варіант — скористатися оператором if-else:

int age = 25;
int money;
if (age > 30)
   money = 100;
else
   money = 50;

Другий варіант — використати тернарний оператор, тобто скорочений запис оператора if-else:

int age = 25;
int money = age > 30 ? 100 : 50;

Тож що краще використовувати: оператор if-else чи тернарний оператор? З точки зору швидкості виконання, особливої різниці немає. Тут швидше питання читабельності коду. І це дуже важливий момент: код повинен не тільки правильно працювати, але й легко читатися іншими програмістами.

Найпростіший критерій може бути таким: якщо код вміщується в один рядок — використовуйте тернарний оператор, якщо в один рядок він вже не вміщується — краще використовувати if-else.



3. Порівняння дійсних чисел

Як уже говорилося раніше, просто так порівнювати дійсні числа не можна: в процесі роботи з ними завжди можуть виникати несподівані ефекти через те, що частина значущих цифр відкидається.

Тому є перевірений часом підхід. Якщо два дійсні числа відрізняються на дуже маленьке значення, значить можна вважати їх рівними. Приклад:

double a = 1.000001;
double b = 1.000002;
if ( (b - a) < 0.0001 )
   System.out.println("Числа рівні");
else
   System.out.println("Числа не рівні");

Але це ще не все: різниця чисел цілком може виявитися від'ємним числом. Тому, щоб такий підхід працював, потрібно порівнювати не просто різницю чисел, а модуль різниці чисел: |a-b|

У Java є спеціальний метод для обчислення модуля числа — Math.abs():

int m = Math.abs(значення);

Тому виправлений варіант нашого прикладу вище виглядатиме ось так:

double a = 1.000001;
double b = 1.000002;

if ( Math.abs(b - a) < 0.0001 )
   System.out.println("Числа рівні");
else
   System.out.println("Числа не рівні");

Коментарі (20)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Alya Kasta Рівень 8
5 березня 2025
Теж стикнулась з проблемою в останньому завданні, може комусь буде корисне моє пояснення чому if(Math.abs(b - a) < 0.000001) вірно а if(Math.abs(b - a) == 0) не вірно В частині Math.abs(b - a) - обчислює модуль різниці між числами Значення 0.000001 - це поріг точності для порівняння double Отже, якщо різниця чисел b - a менша за поріг точності 0.000001 то числа вважаються рівними
Іван Рівень 8
7 листопада 2024
Написав так "... if (Math.abs(firstDouble-secondDouble) < 0.000001); { ..." зарахувало помилку, тому що після виразу не треба було ставити крапку з комою, а відразу фігурну дужку..., поки я до тямив - пройшло десь 3 хвилини🤪
Михайло Рівень 4
16 серпня 2024
я теж не можу зрозуміти чого треба писати так: if (Math.abs(s - f) < 0.000001) { System.out.println("числа рівні"); } else { System.out.println("числа не рівні"); а не замінити на: if (s - f == 0)
hidden #3500645 Рівень 30
22 листопада 2024
При порівнянні дійсних чисел (типів float або double) у Java використовують віднімання змінних і перевіряють, чи різниця менша за певний поріг (так званий epsilon, тобто модуль різниці), тому що дійсні числа в пам’яті комп'ютера представляються з кінцевою точністю. Через обмеження формату з плаваючою комою в IEEE 754 можуть виникати помилки округлення, які унеможливлюють точне порівняння дійсних чисел. Основні причини: 1. Обмежена точність представлення чисел: Наприклад, число 0.1 не може бути представлено точно в двійковій системі, тому арифметичні операції з ним можуть призводити до накопичення похибок. 2. Похибки обчислень: При виконанні операцій, таких як ділення, множення або віднімання, похибки округлення накопичуються, і результат може трохи відрізнятися від очікуваного. 3. Формат IEEE 754: Це стандарт для представлення чисел з плаваючою комою, але через кінцеву кількість бітів, відведених для мантиси та експоненти, зберігається лише наближене значення числа.
hidden #3500645 Рівень 30
22 листопада 2024
Як це працює: Використовується поріг epsilon (ε), який є дуже малим числом. Замість того щоб перевіряти рівність чисел a і b через a == b, обчислюють модуль їх різниці і перевіряють, чи вона менша за epsilon:

if (Math.abs(a - b) < epsilon) {
    // Числа вважаються рівними
}
Приклад:

public class FloatComparison {
    public static void main(String[] args) {
        double a = 0.1 + 0.2; // Очікуємо 0.3
        double b = 0.3;

        // Порівняння з epsilon
        double epsilon = 1e-9;
        if (Math.abs(a - b) < epsilon) {
            System.out.println("a і b рівні");
        } else {
            System.out.println("a і b НЕ рівні");
        }
    }
}

У цьому прикладі 0.1 + 0.2 не дорівнює точно 0.3 через похибки округлення, тому порівняння через == поверне false. Використання epsilon допоможе правильно оцінити, що ці числа достатньо близькі для вважання їх рівними.
Anonymous #3398391 Рівень 4
27 лютого 2024
Не знаю, що там люди не розуміють в останньому завданні, але я написав свій код

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		System.out.print("Введіть число a: ");
		double a = s.nextDouble();
		System.out.print("Введіть число b: ");
		double b = s.nextDouble();
		System.out.println((a > b)? "a > b" : "a < b");		
	}
}
15 жовтня 2023
Написав "Числа не рівні" з великої, зарахувало як помилку)
Владислав Рівень 6
9 липня 2023
Не розумію чому треба вказувати діапазон чому просто не можна написати if ( x == y)... , де x та y дійсні числа. Хто пояснить, буду вдячним
Timmofeii Рівень 9
3 вересня 2023
Приветсвую. это для того чтобы понимать "важную" часть числа и то на что можно закрыть "глаза" если пользоловаться if ( x == y) то у тебя Х должно полностью совпадать с У то есть 1==1 правда будет, а 1.01=1 будет false, а в случае возможности еонмортного учитывания погрешности привели данный пример. надеюсь смог обьяснить😅
Polyhedal Рівень 3
2 вересня 2022
Почему System.out.println(numberA > numberB ? numberA : numberB); и int max = numberA > numberB ? System.out.println(numberA) : System.out.println(numberB); не одно и то же? В лекции тернарный оператор показывается через переменную инт, а код не пропускает такой.
Igor Рівень 6
10 вересня 2022
Аналогичный вопрос
Savichon Рівень 17
15 вересня 2022
В 2 варіанті ти прирівнюєш до змінної int max вираз System.out.println(), тому і не вірно
Ivanka K Рівень 3
23 вересня 2022
мій варіант теж інший, ніби коротший: int max = numberA > numberB ? numberA : numberB; System.out.println(max);
Ivanka K Рівень 3
23 вересня 2022
думаю, що System.out.println - це команда, а оператор працює з виразами тобто int max можна присвоїти значення виразу, а це значення береться з вибору двох значень, а не двох команд, тобто тернарний оператор для присвоєння значень через вибір, а не для вибору команд
Ivanka K Рівень 3
23 вересня 2022
тобто чинаючи вашу умову в такому вигляді я розумію таке: цілому числу з іменем мах присвоїти значення числа при умові, якщо numberA > numberB ? і тут програма очікує на число типу int і ми маємо дати їй 2 такі варіанти а Ви даєте 2 команди, причому для виводу в консоль, а вона хоче просто 2 варіанти чисел для вибору виходить що в цьому разі int max нічого не присвоєно
Roma Chernesh Рівень 16
20 листопада 2022
у прикладі з лекції нічого не виводили на екран. тут задачка була на логіку (ну, чи перевірка, хоча б загуглиш ти чі ні) У цьому випадку не можна записати у зміну max типу int значення System.out.println(...) Тобто ще раз: System.out.println(numberA > numberB ? numberA : numberB); тут ми виводимо на екран значення змінної типу int а у твоєму коді: int max = numberA > numberB ? System.out.println(numberA) у змінну типу int призначають не цифру, а команду, що виводить текст у консоль (що не подобається компілятору, бо Java так не працює)
kora Рівень 6
13 липня 2022
в последнем задании тяжко было 🤯
Polyhedal Рівень 3
2 вересня 2022
переписать пример, добавив нули? 🤔😬
Oleksii Klym Рівень 11
6 жовтня 2022
звідки ти знаєш, що він саме про нулі??? до прикладу, я не міг зрозуміти в чому проблема, так як в коді ти пишеш крапку. А от чому в консолі ти повинен писати кому замість крапки не зрозуміло.... але раз так працює то нехай
Maxim Рівень 6
3 червня 2023
та ні, все дуже легко