Тернарная операция (тернарный условный оператор) – это выражение, выбирающее одно из двух подвыражений на основании булева условия, при этом остаётся именно выражением, то есть имеет значение и (в типизированных ЯП) тип. В императивных языках семейства C запись обычно имеет вид cond ? expr1 : expr2, в Python – эквивалент expr1 if cond else expr2. Тернарная операция эквивалентна конструкции if–else, но компактнее и позволяет встраивать выбор внутрь более сложных выражений. Для задач ЕГЭ по информатике владение тернарной формой полезно: ей удобно оформлять кусочно-заданные функции, вычислять минимум/максимум, «зажимать» значения в диапазон, компактно кодировать логические ветвления без побочных эффектов.
Формальная семантика
Пусть cond – булев предикат, E1, E2 – выражения. Тернарная операция определяется правилом:
Типизация и приведения
Статически типизированные ЯП требуют согласования типов E1 и E2. Обычно действует правило поиска общего типа:
В языках C-подобного синтаксиса тернарный оператор имеет низкий приоритет (ниже логических &&/||, выше операторов присваивания) и правую ассоциативность:
a ? b : c ? d : e // парсится как a ? b : (c ? d : e)
Поэтому многоуровневые тернарные выражения обязательно скобочить, чтобы избежать двусмысленности и ошибок чтения. В Python приоритет выражения «A if cond else B» как у обычного выражения; скобки также рекомендуются при вкладывании.
Эквивалентность if–else
Следующие формы эквивалентны по значению:
// C-подобные ЯП
y = cond ? E1 : E2;
// Эквивалентно
if (cond) y = E1;
else y = E2;
Семантическое отличие: тернарная версия – единое выражение, его можно использовать в качестве аргумента функции, части более длинной формулы, элемента литерала массива и т. д.
Побочные эффекты и безопасность
Из-за ленивой оценки безопасно писать:
int safe_div(int a, int b) { return b != 0 ? a / b : 0; }
Ветвь a / b не будет вычислена при b == 0. Однако недопустимо дублировать выражения с побочными эффектами в обеих ветвях или в условии так, чтобы они выполнялись неожиданное количество раз. Хорошая практика – держать ветви чистыми (без изменений внешнего состояния) или вынести побочные эффекты наружу.

Выбирайте тернарный оператор, когда нужен результат как часть выражения. Для длинной логики и сложных побочных эффектов предпочтителен явный if–else.
Соблюдайте типовую согласованность ветвей. Не смешивайте несоизмеримые типы; при необходимости приводите явно.
Ограничивайте вложенность. Рекомендация: не более одной вложенности; при двух и более – обязательно скобки и комментарий.
Соблюдайте читаемость. Короткие ветви – в одну строку; длинные – форматируйте по строкам:
result = (
val1 if cond1 else
val2 if cond2 else
val3
)
Опирайтесь на ленивую семантику. Тернарный оператор корректен для «охранных» вычислений (деление/индексация/вызов только при допустимости условий).
Не перепоручайте тернарному оператору управление побочными эффектами. Если обе ветви должны что-то менять – лучше if–else.
Минимум/максимум: min = a < b ? a : b; / max = a > b ? a : b;
Зажим (clamp): x = x < lo ? lo : (x > hi ? hi : x);
Знак числа: sign = (x > 0) ? 1 : ((x < 0) ? -1 : 0);
Выбор единиц измерения/окончаний:
word = «байт» if n % 10 == 1 and n % 100 != 11 else «байта» if 2 <= n % 10 <= 4 and not 12 <= n % 100 <= 14 else "байт"
Безопасная индексация/деление/вызов: b ? a/b : backup;, i < len(a) ? a[i] : default;
В заданиях ЕГЭ часто встречаются:
кусочно-заданные функции и вычисления по условиям («если A, то f₁, иначе f₂»), которые удобно писать тернарно;
минимум/максимум, ограничение диапазона, выбор формата вывода;
логические преобразования (сокращение if–else в выражение для последующих вычислений);
подсчёты с защитой от ошибок (деление на ноль, выход за границы).
Умение чётко формулировать условие и ветви, помнить приоритет и ассоциативность, а также опираться на ленивую оценку повышает скорость и надёжность решения.
Приоритет против логики:
// ПЛОХО: непреднамеренная группировка
x = a && b ? u : v; // читается как x = (a && b) ? u : v; – это ок
x = a && (b ? u : v); // совсем другая логика!
Чётко расставляйте скобки по реальному замыслу.
Смешивание с присваиванием:
cond ? x = f() : y = g(); – плохо (зависимые побочные эффекты, синтаксические ловушки). Разворачивайте:
if (cond) x = f(); else y = g();
Разные типы ветвей:
cond ? 0 : «error» – в статически типизированных ЯП вызовет ошибку или нежелательное приведение; приводите явно или используйте единый тип результата.
C/C++/Java/JavaScript/C#: cond ? expr1 : expr2 (правая ассоциативность, ленивое вычисление).
Python: expr1 if cond else expr2 (те же семантические свойства).
Псевдокод ЕГЭ: допустимы обе формы; главное – однозначность и корректность логики.
Упражнение 1. Расставьте скобки и вычислите значение
Задание. Для a=2, b=5, c=3, d=7 вычислите выражение:
E = a < b ? b - a : c > d ? c : d
Решение. Тернарный оператор правоассоциативен:
E = (a < b) ? (b - a) : ((c > d) ? c : d)
Подстановка: a < b → 2 < 5 → истина ⇒ берём левую ветвь b - a = 5 - 2 = 3.
Ответ: E = 3.
Упражнение 2. Кусочно-заданная функция
Задание. Реализуйте функцию:

Запишите одним тернарным выражением (С-подобный синтаксис и Python), затем вычислите f(-3) , f(-4) , f(-12).
Решение.
C-подобный синтаксис: int f(int x){ return x < 0 ? x*x : (x < 10 ? 2*x + 1 : 10); }
Python: def f(x): return (x*x) if x < 0 else (2*x + 1) if x < 10 else 10
Вычисления: f(-3)=9, f(4)=2*4+1=9, f(12)=10.
Ответ: 9, 9, 10.
Упражнение 3. Зажатие значения в диапазон (clamp)
Задание. Ограничьте x диапазоном [L, R] тернарным выражением без вызова сторонних функций: если x < L – вернуть L, если x > R – R, иначе x. Проверьте для x=-5, L=0, R=3 и x=7, L=0, R=3.
Решение.
int clamp(int x, int L, int R){ return x < L ? L : (x > R ? R : x); }
Проверка:
Упражнение 4. Безопасное деление и ленивая оценка
Задание. Дан код:
int calls = 0;
int heavy(){ calls++; return 42; }
int g(int a, int b){ return (b != 0) ? a/b : heavy(); }
Решение.
g(10,2): условие истинно, выбирается a/b, ветвь heavy() не вычисляется ⇒ calls не растёт.
g(10,0): условие ложно, вычисляется heavy() ⇒ calls увеличится на 1.
Перепись через if–else эквивалентна (та же ленивая семантика по ветвям).
Ответ: 0 вызовов и 1 вызов соответственно; перепись не изменит поведение.
Упражнение 5. Переписывание if–else и анализ типов
Задание. Перепишите фрагмент без изменения типа результата:
double y;
if (x % 2 == 0) y = 0.0;
else y = x;
в тернарной форме. Объясните, почему выражение x % 2 == 0 ? 0 : x потенциально хуже в статически типизированном языке.
Решение. Правильная версия с согласованием типов:
double y = (x % 2 == 0) ? 0.0 : (double)x;
Выражение ? 0 : x содержит целый ноль и, например, в C/Java может спровоцировать неочевидные приведения: компилятор выведет общий тип ветвей (часто int), затем неявно приведёт к double при присваивании, а при дальнейшей композиции это может сломать перегрузки/выбор перегруженных функций. Явное 0.0 и (double)x устраняют двусмысленность.
Ответ: double y = (x % 2 == 0) ? 0.0 : (double)x;.
Тернарная операция – компактный и выразительный инструмент, превращающий ветвление в значение. Её сила – в ленивой семантике, пригодной для «охранных» вычислений, и в возможности строить кусочно-заданные выражения без громоздких if–else. Для успешного применения в задачах ЕГЭ необходимо помнить о:
правой ассоциативности и низком приоритете (скобки!);
согласовании типов ветвей;
допустимой глубине вложенности в интересах читаемости;
преимуществах ленивой оценки и недопустимости «скрытых» побочных эффектов.
Освоив эти правила и отработав типовые идиомы (min/max, clamp, знак, кусочно-заданные функции, безопасное деление), вы получите лёгкий в применении и безопасный инструмент, ускоряющий решение задач и повышающий качество кода.