Тернарна умовна операція (лат. ternarius — «потрійний») (зазвичай записується як ?:
) — у багатьох мовах програмування операція, яка повертає свій другий або третій операнд залежно від значення логічного виразу, заданого першим операндом. Як випливає з назви, тернарна операція приймає всього три вказаних операнди. Аналогом тернарної умовної операції в математичній логіці і булевій алгебрі є умовна диз'юнкція, яка записується у вигляді і реалізує алгоритм: «Якщо , то , інакше », що можна переписати як « або , залежно від або не ».
Зазвичай тернарна умовна операція асоціюється з операцією ?:
, яка використовується в сі-подібних мовах програмування. Насправді, подібні операції з іншим синтаксисом є і в багатьох далеких за синтаксисом від Сі мовах програмування. До найбільш популярних мов, що містять тернарну умовну операцію, можна віднести C, , JavaScript, Swift, Objective-C, C#, D, Java, Perl, PHP, Python, Tcl, Ruby, Verilog, Turbo Basic та інші. Своєю появою безпосередньо в тернарній формі ця операція зобов'язана мові Алгол-60, у якій вона мала синтаксис if o1 then o2 else o3
і потім мови BCPL (o1 -> o2, o3
) замість звичного тепер o1 ? o2 : o3
. Прототипом цієї операції також є умовна функція cond
мови Лісп, яка записується за правилами Ліспа в префіксній формі і має довільну кількість аргументів.
Визначення
Безвідносно до певної мови програмування тернарну операцію можна визначити так:
логічний вираз ? вираз 1 : вираз 2
Алгоритм роботи операції наступний:
- Обчислюється
логічний вираз
. - Якщо
логічний вираз
істинний, то обчислюється значення виразувираз 1
, в іншому разі — значення виразувираз 2
. - Обчислене значення повертається.
Потрібно звернути увагу, що обчислюється тільки один з виразів: вираз 1
або вираз 2
. Це відповідає принципу лінивих обчислень, і зроблено не так для оптимізації, як для розширення можливостей: так, вираз x < 0 ? 0 : sqrt(x)
абсолютно коректний, незважаючи на те, що корінь з від'ємних чисел не береться.
Використання і реалізація
Тернарна умовна операція використовується у виразах для отримання одного з двох варіантів залежно від умови.
alarm_time = today in [SUNDAY, MONDAY] ? 12.00 : 8.00
У цьому прикладі умовного електронного будильника виставляється час, коли він повинен дзвонити, залежно від дня тижня. Потрібно зауважити, що приклад знову наведений для деякої абстрактної алгоритмічної мови програмування.
У наступному прикладі обчислюється значення найпростішого дельта-символу.
y = x == 0 ? 1 : 0
У наступному прикладі дана операція використана в ситуації, не пов'язаній з присвоюванням:
sprintf( Title, "%s %s", tv_system == TV_PAL ? "PAL" : "SECAM", tv_input ? Tv_Name[ tv_input - 1 ]: "TEST" );
У цьому разі еквівалентна конструкція з використанням if
—then
—else
вимагала б запису виклику функції sprintf
чотири рази. Або, як альтернатива, треба було б написати аналогічний за призначенням (але формально не еквівалентний) код з використанням двох додаткових змінних або декількох послідовних викликів sprintf
.
С
У Сі тернарна операція має наступний синтаксис:
o1 ? o2 : o3
Як відомо,[] у Сі немає логічного типу даних (у C99 з'явився логічний тип _Bool
). Тому операнд o1
повинен бути числом (цілим або дійсним) або вказівником. Спочатку обчислюється саме його значення. Воно порівнюється з нулем і, якщо воно не дорівнює нулю, обчислюється і повертається o2
, у разі рівності — o3
. Операнди o2
і o3
можуть бути різних, кажучи загалом, незбіжних типів, зокрема void
.
У наступному прикладі обчислюється мінімальне з чисел a
і b
:
min = (a < b) ? a : b;
C++
У C++ тернарна умовна операція має той самий синтаксис, що й у Сі. Однак через наявність різниці між ініціалізацією і присвоюванням, бувають ситуації, коли операцію ?:
не можна замінити конструкцією 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
a = 42 b = 41 result = a if a > b else b assert result == 42
PHP
$a = 1==0 ? "first value" : (2==0 ? "second value" : (3==3 ? "result value" : "default value"));
Тернарний оператор у PHP еквівалентний більш довгій конструкції if
—else
. Наступні два приклади еквівалентні:
// Перший приклад $result = isset($a) ? $a : 'DefaultValue'; // Дргуий приклад if (isset($a)) { $result = $a; } else { $result = 'DefaultValue'; }
Такі конструкції часто застосовуються, щоб у будь-якому разі ініціалізувати змінну для наступних обчислень (інакше PHP видасть помилку рівня E_NOTICE
).
Починаючи з версії 5.3 з'явилася можливість не вказувати другий параметр операції. Наприклад, два наступних записи еквівалентні:
$Variable = $_GET['Parameter'] ? $_GET['Parameter'] : 'DefaultValue'; $Variable = $_GET['Parameter'] ?: 'DefaultValue';
JavaScript
var a = 1==0 ? "first value" : 2==0 ? "second value" : 3==3 ? "result value" : "default value"
Ruby
Загальний синтаксис аналогічний C-подібним мовам.
print true ? "true" : "false" # Виведе true в стандартний вивід
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;
Visual Basic
У класичній версії мови існує тернарний оператор у вигляді функції IIf(Expr, TruePart, FalsePart)
. Ця функція має певну особливість, яка полягає в тому, що під час оцінки виразу Expr
, також будуть обчислюватися TruePart
і FalsePart
, незалежно від результату виразу: істинний він чи хибний. Це може призвести до несподіваних результатів, а іноді й до вповільнення виконання коду, якщо в ролі значень буде виклик функцій з тривалими операціями.
Dim iCount As Long Public Sub Main() iCount = 1 MsgBox IIf(1 = 1, FuncYes, FuncNo) 'Змінна iCount буде містити "3", оскільки обидві функції будуть виконані MsgBox iCount End Sub Public Function FuncYes() As String iCount = iCount + 1 FuncYes = "Так" End Function Public Function FuncNo() As String iCount = iCount + 1 FuncNo = "Ні" End Function
Для заміни функції IIf
можна переписати вираз в один рядок, але це не буде аналогом функції, а буде лише коротка форма запису оператора розгалуження
If Expr Then TruePart Else FalsePart
З появою VB.NET, у синтаксис мови був доданий звичний тернарний оператор і записується він як If(Expr, TruePart, FalsePart)
. Цей оператор використовує скорочені обчислення, на відміну від функції IIf
, яка також для сумісності з попередніми версіями доступна розробнику.
Turbo Basic
Синтаксис: IF logic_expression [<> 0] [,] THEN statement(s) [ELSE statement(s)]
Будь-який результат logic_expression
не рівний 0 вважається %FALSE
, але не %TRUE
, рівний тільки -1. logic_expression
може бути числовим (numeric), так і символьним (string). У разі символьного виразу обчислення проводяться з ASCII-кодами символів.
%TRUE = -1 %FALSE = 0 A$ = "M" B$ = "N" C! = 43 D# = 44 IF A$>B$ <> %FALSE, THEN RESULT# = C! ELSE RESULT# = D# PRINT RESULT#
За допомогою функції FN IfThenElse(X1,X2,X3)
, замість інфіксного виду тернарного оператора If Then X1 X2 Else X3
можна користуватися префіксним видом тернарного оператора IfThenElse
:
A$ = "M" B$ = "N" C! = 43 D# = 44 COND = A$<B$ 'COND = любое logic_expression PRINT "FN IfThenElse(X1,X2,X3) =";FN IfThenElse(COND,C!,D#) END DEF FN IfThenElse(X1,X2,X3) IF X1 <> 0 THEN FN IfThenElse = X2 ELSE FN IfThenElse = X3 END DEF
Примітки
- BCPL Ternary operator (page 15) (PDF). BCPL Reference Manual. Архів оригіналу (PDF) за 31 березня 2012. Процитовано 28 вересня 2017.
- Ю. Ю. Громов, С. И. Татаренко. Программирование на языке СИ.
- Б. Страуструп. .
- Оператор
?:
(C#) // https://msdn.microsoft.com/ru-ru/library/ty67wk28.aspx - Оператор If (Visual Basic) // https://msdn.microsoft.com/ru-ru/library/bb513985.aspx
- Borland Turbo BASIC Owners Handbook 1987
Ця стаття потребує додаткових для поліпшення її . (жовтень 2017) |
Це незавершена стаття про мови програмування. Ви можете проєкту, виправивши або дописавши її. |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
U Vikipediyi ye statti pro inshi znachennya cogo termina Operaciya Ternarna umovna operaciya lat ternarius potrijnij zazvichaj zapisuyetsya yak u bagatoh movah programuvannya operaciya yaka povertaye svij drugij abo tretij operand zalezhno vid znachennya logichnogo virazu zadanogo pershim operandom Yak viplivaye z nazvi ternarna operaciya prijmaye vsogo tri vkazanih operandi Analogom ternarnoyi umovnoyi operaciyi v matematichnij logici i bulevij algebri ye umovna diz yunkciya yaka zapisuyetsya u viglyadi p q r displaystyle p q r i realizuye algoritm Yaksho p displaystyle p to q displaystyle q inakshe r displaystyle r sho mozhna perepisati yak q displaystyle q abo r displaystyle r zalezhno vid p displaystyle p abo ne p displaystyle p Zazvichaj ternarna umovna operaciya asociyuyetsya z operaciyeyu yaka vikoristovuyetsya v si podibnih movah programuvannya Naspravdi podibni operaciyi z inshim sintaksisom ye i v bagatoh dalekih za sintaksisom vid Si movah programuvannya Do najbilsh populyarnih mov sho mistyat ternarnu umovnu operaciyu mozhna vidnesti C C JavaScript Swift Objective C C D Java Perl PHP Python Tcl Ruby Verilog Turbo Basic ta inshi Svoyeyu poyavoyu bezposeredno v ternarnij formi cya operaciya zobov yazana movi Algol 60 u yakij vona mala sintaksis b if b o1 b then b o2 b else b o3 i potim movi BCPL o1 gt o2 o3 zamist zvichnogo teper o1 o2 span span o3 Prototipom ciyeyi operaciyi takozh ye umovna funkciya cond movi Lisp yaka zapisuyetsya za pravilami Lispa v prefiksnij formi i maye dovilnu kilkist argumentiv ViznachennyaBezvidnosno do pevnoyi movi programuvannya ternarnu operaciyu mozhna viznachiti tak logichnij viraz viraz 1 viraz 2 Algoritm roboti operaciyi nastupnij Obchislyuyetsya logichnij viraz Yaksho logichnij viraz istinnij to obchislyuyetsya znachennya virazu viraz 1 v inshomu razi znachennya virazu viraz 2 Obchislene znachennya povertayetsya Potribno zvernuti uvagu sho obchislyuyetsya tilki odin z viraziv viraz 1 abo viraz 2 Ce vidpovidaye principu linivih obchislen i zrobleno ne tak dlya optimizaciyi yak dlya rozshirennya mozhlivostej tak viraz x lt 0 0 span span sqrt x absolyutno korektnij nezvazhayuchi na te sho korin z vid yemnih chisel ne beretsya Vikoristannya i realizaciyaTernarna umovna operaciya vikoristovuyetsya u virazah dlya otrimannya odnogo z dvoh variantiv zalezhno vid umovi alarm time today in SUNDAY MONDAY 12 00 8 00 U comu prikladi umovnogo elektronnogo budilnika vistavlyayetsya chas koli vin povinen dzvoniti zalezhno vid dnya tizhnya Potribno zauvazhiti sho priklad znovu navedenij dlya deyakoyi abstraktnoyi algoritmichnoyi movi programuvannya U nastupnomu prikladi obchislyuyetsya znachennya najprostishogo delta simvolu y x 0 1 0 U nastupnomu prikladi dana operaciya vikoristana v situaciyi ne pov yazanij z prisvoyuvannyam sprintf Title s s tv system TV PAL PAL SECAM tv input Tv Name tv input 1 TEST U comu razi ekvivalentna konstrukciya z vikoristannyam if then else vimagala b zapisu vikliku funkciyi sprintf chotiri razi Abo yak alternativa treba bulo b napisati analogichnij za priznachennyam ale formalno ne ekvivalentnij kod z vikoristannyam dvoh dodatkovih zminnih abo dekilkoh poslidovnih viklikiv sprintf S U Si ternarna operaciya maye nastupnij sintaksis o1 o2 o3 Yak vidomo komu u Si nemaye logichnogo tipu danih u C99 z yavivsya logichnij tip Bool Tomu operand o1 povinen buti chislom cilim abo dijsnim abo vkazivnikom Spochatku obchislyuyetsya same jogo znachennya Vono porivnyuyetsya z nulem i yaksho vono ne dorivnyuye nulyu obchislyuyetsya i povertayetsya o2 u razi rivnosti o3 Operandi o2 i o3 mozhut buti riznih kazhuchi zagalom nezbizhnih tipiv zokrema void U nastupnomu prikladi obchislyuyetsya minimalne z chisel a i b min a lt b a b C U C ternarna umovna operaciya maye toj samij sintaksis sho j u Si Odnak cherez nayavnist riznici mizh inicializaciyeyu i prisvoyuvannyam buvayut situaciyi koli operaciyu ne mozhna zaminiti konstrukciyeyu if then else yak napriklad u nastupnomu vipadku include lt iostream gt include lt fstream gt include lt string gt using namespace std int main int argc char argv string name ofstream fout if argc gt 1 amp amp argv 1 name argv 1 fout open name c str ios out ios app ostream amp sout name empty cout fout return 0 Tut zminna sout inicializuyetsya v moment ogoloshennya rezultatom roboti ternarnoj operaciyi Podibnogo efektu ne vdalosya b dosyagti prostim prisvoyuvannyam u tomu chi inshomu vipadku Krim togo ternarna umovna operaciya mozhe buti zastosovana v livij chastini operatora prisvoyennya 0 include lt iostream gt 1 int main 2 3 int a 0 b 0 4 5 const bool cond 6 cond a b 1 7 std cout lt lt a lt lt a lt lt 8 lt lt b lt lt b lt lt n 9 U comu prikladi yaksho logichna zminna cond u ryadku 5 mistitime znachennya true to znachennya 1 bude prisvoyeno zminnij a inakshe vono bude prisvoyeno zminnij b Python a 42 b 41 result a if a gt b else b assert result 42 PHP a 1 0 first value 2 0 second value 3 3 result value default value Ternarnij operator u PHP ekvivalentnij bilsh dovgij konstrukciyi if else Nastupni dva prikladi ekvivalentni Pershij priklad result isset a a DefaultValue Drguij priklad if isset a result a else result DefaultValue Taki konstrukciyi chasto zastosovuyutsya shob u bud yakomu razi inicializuvati zminnu dlya nastupnih obchislen inakshe PHP vidast pomilku rivnya E NOTICE Pochinayuchi z versiyi 5 3 z yavilasya mozhlivist ne vkazuvati drugij parametr operaciyi Napriklad dva nastupnih zapisi ekvivalentni Variable GET Parameter GET Parameter DefaultValue Variable GET Parameter DefaultValue JavaScript var a 1 0 first value 2 0 second value 3 3 result value default value Ruby Zagalnij sintaksis analogichnij C podibnim movam print true true false Vivede true v standartnij vivid C Na ternarnu operaciyu nakladayutsya dodatkovi obmezhennya pov yazani z tipobezpekoyu Virazi 1 i 2 povinni buti odnogo tipu Ce prizvodit do nastupnogo int a 1 double b 0 0 int nMax a gt b a b Takij vihidnij kod ne kompilyuvatimetsya nezvazhayuchi na te sho v kincevomu pidsumku znachennya nMax dorivnyuvatime a Oskilki a i b povinni buti odnogo tipu a pidvishitsya do double shob vidpovidati b Tip rezultivnogo znachennya ternarnoyi operaciyi viyavlyayetsya double i cej tip povinen buti znizhenij do int pid chas prisvoyennya int a 1 double b 0 0 int nMax Mozhna vchiniti tak nMax int a gt b a b abo tak nMax a gt b a int b Visual Basic U klasichnij versiyi movi isnuye ternarnij operator u viglyadi funkciyi IIf Expr TruePart FalsePart Cya funkciya maye pevnu osoblivist yaka polyagaye v tomu sho pid chas ocinki virazu Expr takozh budut obchislyuvatisya TruePart i FalsePart nezalezhno vid rezultatu virazu istinnij vin chi hibnij Ce mozhe prizvesti do nespodivanih rezultativ a inodi j do vpovilnennya vikonannya kodu yaksho v roli znachen bude viklik funkcij z trivalimi operaciyami Dim iCount As Long Public Sub Main iCount 1 MsgBox IIf 1 1 FuncYes FuncNo Zminna iCount bude mistiti 3 oskilki obidvi funkciyi budut vikonani MsgBox iCount End Sub Public Function FuncYes As String iCount iCount 1 FuncYes Tak End Function Public Function FuncNo As String iCount iCount 1 FuncNo Ni End Function Dlya zamini funkciyi IIf mozhna perepisati viraz v odin ryadok ale ce ne bude analogom funkciyi a bude lishe korotka forma zapisu operatora rozgaluzhennya If Expr Then TruePart Else FalsePart Z poyavoyu VB NET u sintaksis movi buv dodanij zvichnij ternarnij operator i zapisuyetsya vin yak If Expr TruePart FalsePart Cej operator vikoristovuye skorocheni obchislennya na vidminu vid funkciyi IIf yaka takozh dlya sumisnosti z poperednimi versiyami dostupna rozrobniku Turbo Basic Sintaksis b IF b logic expression lt gt 0 b THEN b statement s b ELSE b statement s Bud yakij rezultat logic expression ne rivnij 0 vvazhayetsya FALSE ale ne TRUE rivnij tilki 1 logic expression mozhe buti chislovim numeric tak i simvolnim string U razi simvolnogo virazu obchislennya provodyatsya z ASCII kodami simvoliv TRUE 1 FALSE 0 A M B N C 43 D 44 IF A gt B lt gt FALSE THEN RESULT C ELSE RESULT D PRINT RESULT Za dopomogoyu funkciyi FN IfThenElse X1 X2 X3 zamist infiksnogo vidu ternarnogo operatora If Then X1 X2 Else X3 mozhna koristuvatisya prefiksnim vidom ternarnogo operatora IfThenElse A M B N C 43 D 44 COND A lt B COND lyuboe logic expression PRINT FN IfThenElse X1 X2 X3 FN IfThenElse COND C D END DEF FN IfThenElse X1 X2 X3 IF X1 lt gt 0 THEN FN IfThenElse X2 ELSE FN IfThenElse X3 END DEFPrimitkiBCPL Ternary operator page 15 PDF BCPL Reference Manual Arhiv originalu PDF za 31 bereznya 2012 Procitovano 28 veresnya 2017 Yu Yu Gromov S I Tatarenko Programmirovanie na yazyke SI B Straustrup Mova programuvannya S Operator C https msdn microsoft com ru ru library ty67wk28 aspx Operator If Visual Basic https msdn microsoft com ru ru library bb513985 aspx Borland Turbo BASIC Owners Handbook 1987 Cya stattya potrebuye dodatkovih posilan na dzherela dlya polipshennya yiyi perevirnosti Bud laska dopomozhit udoskonaliti cyu stattyu dodavshi posilannya na nadijni avtoritetni dzherela Zvernitsya na storinku obgovorennya za poyasnennyami ta dopomozhit vipraviti nedoliki Material bez dzherel mozhe buti piddano sumnivu ta vilucheno zhovten 2017 Ce nezavershena stattya pro movi programuvannya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi