Тернарная условная операция

Тернарная условная операция

Терна́рная усло́вная опера́ция (от лат. ternarius — «тройной») (обычно записывается как ?:) — во многих языках программирования операция, возвращающая свой второй или третий операнд в зависимости от значения логического выражения, заданного первым операндом. Как можно судить из названия, тернарная операция принимает всего три указанных операнда. Аналогом тернарной условной операции в математической логике и булевой алгебре является условная дизъюнкция, которая записывается в виде [p, q, r] и реализует алгоритм: «Если q, то p, иначе r», что можно переписать как «p или r, в зависимости от q или не q».

Обычно тернарная условная операция ассоциируется с операцией ?:, используемой в си-подобных языках программирования. На самом деле, подобные операции с другим синтаксисом имеются и во многих далёких по синтаксису от Си языках программирования. К наиболее популярным языкам, содержащим тернарную условную операцию, можно отнести C, C++, JavaScript, Objective-C, C#, D, Java, ECMAScript, Perl, PHP, Python,Tcl, Ruby, Verilog и другие. Своим появлением непосредственно в тернарной инфиксной форме эта операция обязана языку Алгол-60, в котором она имела синтаксис if o1 then o2 else o3 и затем языку BCPL (o1 -> o2, o3)[1] вместо привычного теперь o1 ? o2 : o3. Прототипом же этой операции, в свою очередь, является условная функция cond языка Лисп, записываемая по правилам Лиспа в префиксной форме и имеющая произвольное количество аргументов.

Содержание

Определение

Безотносительно определённого языка программирования, тернарную операцию можно определить так:

логическое выражение ? выражение 1 : выражение 2

Алгоритм работы операции следующий:

  1. Вычисляется логическое выражение.
  2. Если логическое выражение истинно, то вычисляется значение выражения выражение 1, в противном случае — значение выражения выражение 2.
  3. Вычисленное значение возвращается.

Нужно обратить внимание, что вычисляется только одно из выражений: выражение 1 или выражение 2. Это сделано для оптимизации и, в некотором смысле, соответствует принципу ленивых вычислений.

Использование и реализации

Тернарная условная операция используется в выражениях для получения одного из двух вариантов в зависимости от условия.

alarm_time = today in [SUNDAY, MONDAY] ? 12.00 : 8.00

В этом примере условному программируемому электронному будильнику проставляется время, в которое он должен звонить, в зависимости от текущего дня недели. Нужно заметить, что пример снова приведён для некоторого абстрактного алгоритмического языка программирования.

В следующем примере вычисляется значение простейшего дельта-символа.

y = x == 0 ? 1 : 0

В действительности, немедленное присваивание результата тернарной условной операции редко оправдано с точки зрения стиля программирования, так как подобные операторы компактно переписываются в виде эквивалентной конструкции if-then-else. Более оправдано использование данной операции в более сложных конструкциях, не связанных с присваиванием, например в фактических параметрах вызова функции:

sprintf(Title, "%s %s",
           tv_system == TV_PAL ? "PAL" : "SECAM",
           tv_input == 0 ? "TEST" : Tv_Name[tv_input-1]);

В данном случае эквивалентная конструкция с использованием if-then-else потребовала бы записи вызова функции sprintf четыре раза. Либо, в качестве альтернативы, потребовалось бы написать аналогичный по назначению (но формально не эквивалентный) код с использованием двух дополнительных временных переменных, либо нескольких последовательных вызовов sprintf.

Си

В Си тернарная операция имеет следующий синтаксис:[2]

o1 ? o2 : o3

Как известно, в Си нет логического типа данных (в C99 появился логический тип _Bool). Поэтому операнд o1 должен быть числом (целым или вещественным) или указателем. Сначала вычисляется именно его значение. Оно сравнивается с нулём и, если оно не равно нулю, вычисляется и возвращается o2, в случае равенства — o3. Операнды o2 и o3 могут быть различных, вообще говоря, несовпадающих типов, включая void.

В следующем примере вычисляется минимальное из чисел a и b:

min = (a < b) ? a : b;

C++

В C++ тернарная условная операция имеет тот же синтаксис, что и в Си.[3] Однако за счёт наличия разницы между инициализацией и присваиванием, бывают ситуации, когда операцию ?: нельзя заменить конструкцией if-then-else, как, например, в следующем случае:

#include <iostream>
#include <fstream>
#include <string>
 
using namespace std;
 
int main(int argc, char** argv)
{
    string name;
    ofstream fout;
    if (argc > 1 && argv[1])
    {
        name = argv[1];
        fout.open(name.c_str(), ios::out | ios::app);
    }
    ostream& sout = name.empty() ? cout : fout;
    return 0;
}

Здесь переменная sout инициализируется в момент объявления результатом работы тернарной операции. Подобного эффекта не удалось бы достичь простым присваиванием в том или ином случае.

Кроме того, тернарная условная операция может быть применена в левой части оператора присвоения:

0. #include <iostream>
1. int main () 
2. {
3.     int a=0, b=0;
4. 
5.     const bool cond = ...;
6.     (cond ? a : b) = 1;
7.     std::cout << "a=" << a << ','
8.               << "b=" << b << '\n';
9. }

В этом примере, если логическая переменная cond в строке 5 будет содержать значение true, то значение 1 будет присвоено переменной a, иначе, оно будет присвоено переменной b.

Python

b = 3
a = 1 if b==1 else \
    2 if b==2 else \
    3
assert a==3

PHP

 $a = 1==0 ? "first value" :
      (2==0 ? "second value" :
      (3==3 ? "result value" : "default value"));

Начиная с версии 5.3 появилась возможность не указывать второй параметр операции. Например, две следующих записи эквивалентны:

 $Variable = $_GET['Parameter'] ? $_GET['Parameter'] : 'DefaultValue';
 $Variable = $_GET['Parameter'] ?: 'DefaultValue';

C#

На тернарную операцию накладываются дополнительные ограничения, связанные с типобезопасностью. Выражения 1 и 2 должны быть одного типа. Это приводит к следующему:

int a = 1;
double b = 0.0;
int nMax = (a>b) ? a : b;

Такой исходный код не будет компилироваться несмотря на то, что в конечном итоге значение nMax будет равно а. Поскольку a и b должны быть одного и того же типа, a повысится до double, чтобы соответствовать b. Тип результирующего значения тернарной операции оказывается double, и этот тип должен быть понижен до int при присваивании:

int a = 1;
double b = 0.0;
int nMax;
// Можно поступить так:
nMax = (int) ((a>b) ? a : b) ;
// ...или так
nMax = (a>b) ? a : (int)b;

Примечания

  1. BCPL Ternary operator (page 15). BCPL Reference Manual. Архивировано из первоисточника 31 марта 2012.
  2. Ю. Ю. Громов, С. И. Татаренко. 1.3.12. Условная операция // Программирование на языке си / Рецензент: профессор А. П. Афанасьев.
  3. Б. Страуструп. 7.13. Условная операция // Справочное руководство по C++.

Литература

Стефан Рэнди Дэвис, Чак Сфер Глава 4. Операторы // C# 2005 для "чайников" = C# 2005 for dummies / под редакцией Т. Г. Сковородниковой. — М.-Спб.: Wiley, Диалектика, 2006. — С. 83. — ISBN 5-8459-1068-4


Wikimedia Foundation. 2010.

Игры ⚽ Нужна курсовая?

Полезное


Смотреть что такое "Тернарная условная операция" в других словарях:

  • Тернарная операция — (от лат. tri три)  операция, имеющая 3 операнда. Примеры: тернарная условная операция в информатике; смешанное векторное произведение; тернарное сложение по модулю 2 в полных сумматорах (с учётом разряда переноса) …   Википедия

  • Условная дизъюнкция — В математической логике, условной дизъюнкцией называется тернарная (имеющая 3 операнда) логическая операция, введенная Чёрчем[1]. Результат условной дизъюнкции аналогичен результату более общей тернарной условной операции (if o1 then o2 else o3) …   Википедия

  • Синтаксический сахар — Эта статья нуждается в дополнительных источниках для улучшения проверяемости. Вы можете помочь улучшить эту статью, добавив ссы …   Википедия

  • Сравнение C Sharp и Java — Правильный заголовок этой статьи  Сравнение C# и Java. Он показан некорректно из за технических ограничений. Сравнения языков программирования Общее сравнение Основной синтаксис Основные инструкции Массивы Ассоциативные массивы Операции со… …   Википедия

  • C++ — У этого термина существуют и другие значения, см. C. См. также: Си (язык программирования) C++ Семантика: мультипарадигмальный: объектно ориентированное, обобщённое, процедурное, метапрограммирование Тип исполнения: компилируемый Появился в …   Википедия

  • Оператор ветвления — (условная инструкция, условный оператор)  оператор, конструкция языка программирования, обеспечивающая выполнение определённой команды (набора команд) только при условии истинности некоторого логического выражения, либо выполнение одной из… …   Википедия

  • ECMAScript — Класс языка: мультипарадигменный: объектно ориентированное, обобщённое, функциональное, императивное, аспектно ориентированное, событийно ориентированное, прототипное программирование Появился в: 1995 Автор(ы) …   Википедия


Поделиться ссылкой на выделенное

Прямая ссылка:
Нажмите правой клавишей мыши и выберите «Копировать ссылку»