Operație condiționată ternară

Operația condiționată ternară (din latină  ternarius  - „triplu”) este o operație implementată în multe limbaje de programare care returnează al doilea sau al treilea operand în funcție de valoarea expresiei logice dată de primul operand. Un analog al operației condiționale ternare în logica matematică și algebra booleană este disjuncția condiționată , care se scrie sub forma și implementează algoritmul: „dacă , atunci , altfel ”.

De obicei, operatorul condițional ternar este asociat cu operatorul ?:utilizat în limbaje de programare asemănătoare C. De fapt, operațiuni similare cu o sintaxă diferită există în multe limbaje de programare care sunt departe de C în sintaxă . Limbile populare care au operatorul condițional ternar încorporat în sintaxa lor sunt C , C++ , JavaScript , Objective-C , C# , D , Java , ECMAScript , Perl , PHP , Python , Tcl , Ruby , Verilog , Turbo Basic . Această operație își datorează apariția direct în forma infixă ternară limbajului Algol-60 , în care avea o sintaxă , iar apoi limbajului BCPL ( ) [1] în locul celui acum familiar . Prototipul acestei operațiuni, la rândul său, este o funcție condiționată a limbajului Lisp , scrisă după regulile Lisp sub formă de prefix și având un număr arbitrar de argumente. if o1 then o2 else o3o1 -> o2, o3o1 ? o2 : o3cond

De obicei, implementarea operației include calculul condiției și doar una dintre expresii, care în unele cazuri oferă capabilități extinse, de exemplu, expresia x > 0 ? 0 : sqrt(x)este considerată corectă, în ciuda faptului că rădăcina nu este luată din numere negative.

Exemple

Simbolul Kronecker :

y = x == 0 ? 1 : 0.

Minim de numere a și b:

min = (a < b) ? a : b

Poate fi folosit într-o situație fără atribuire:

sprintf ( titlu , „%s %s” , tv_system == TV_PAL ? PAL : SECAM , tv_input ? Nume_Tv [ intrare_tv - 1 ] : "TEST" );

- în acest caz, construcția echivalentă folosind if-then-else ar necesita ca apelul funcției să fie scris de sprintfpatru ori.

Limbi asemănătoare C

Basic C nu are un tip de date boolean ( C99 a introdus tipul boolean _Bool), deci primul operand trebuie să fie un număr ( întreg sau real ) sau un pointer [2] ; mai întâi, valoarea sa este calculată și comparată cu zero , iar dacă nu este egală cu zero, al doilea operand este calculat și returnat, în caz de egalitate - al treilea. Al doilea și al treilea operanzi pot fi de diferite tipuri (inclusiv void ).

În C++ , operatorul condițional ternar are aceeași sintaxă ca în C [3] , totuși, din cauza diferenței dintre inițializare și atribuire , există situații în care operația ?:nu poate fi înlocuită cu un construct if-then-else, ca, de exemplu, în cele ce urmează. caz:

#include <iostream> #include <fstream> #include <șir> folosind namespace std ; int main ( int argc , char ** argv ) { stringname ; _ outstream fout ; dacă ( argc > 1 && argv [ 1 ]) { nume = argv [ 1 ]; fout . deschide ( name.c_str ( ), ios :: out | ios :: app ) ; } ostream & sout = nume . gol () ? cout : fout ; returnează 0 ; }

Aici variabila sout este inițializată în momentul în care rezultatul operației ternare este declarat. Un efect similar nu ar putea fi obținut printr-o simplă atribuire într-un caz sau altul.

În plus, operatorul condițional ternar poate fi aplicat în partea stângă a unei instrucțiuni de atribuire:

#include <iostream> int main () { int a = 0 , b = 0 ; const bool cond = ...; ( cond ? a : b ) = 1 ; std :: cout << "a=" << a << ',' << "b=" << b << '\n' ; }

În acest exemplu, dacă variabila booleană cond de pe linia 5 conține valoarea true, atunci valoarea 1 va fi atribuită variabilei a, altfel va fi atribuită variabilei b.

În C# , operatorul ternar are restricții suplimentare legate de siguranța tipului. Expresiile 1 și 2 trebuie să fie de același tip. Acest lucru are ca rezultat următoarele:

int a = 1 ; dublu b = 0,0 ; int nMax = ( a > b ) ? a : b ;

Un astfel de cod sursă nu se va compila, în ciuda faptului că nMax va ajunge să fie un . Deoarece a și b trebuie să fie de același tip, a va fi promovat la dublu pentru a se potrivi cu b . Tipul valorii rezultate a operației ternare este dublu, iar acest tip trebuie să fie redus la int on assignation: [4]

int a = 1 ; dublu b = 0,0 ; int nMax ; // Puteți face acest lucru: nMax = ( int ) (( a > b ) ? a : b ) ; // ...sau așa nMax = ( a > b ) ? a : ( int ) b ;

Python

Python folosește sintaxaif-else cuvintelor cheie :

a = 42 b = 41 rezultat = a dacă a > b altfel b afirmă rezultat == 42

Poate fi implementat și printr-o listă:

[ < expresia 1 > , < expresia 2 > ][ < condiția > ]

- rezultatul expresiei 1 va fi returnat dacă condiția este falsă; și expresia 2 dacă condiția este adevărată. Dacă condiția nu este o expresie booleană, este posibil să depășim lista cu o excepție.

PHP

PHP folosește o sintaxă asemănătoare C :

$a = $b == 1 ? „prima valoare” : ( $b == 2 ? „a doua valoare” : ( $b == 3 ? „valoarea rezultatului” : „valoarea implicită” ));

Operatorul ternar în PHP este echivalent cu constructul mai lung if-else. Următoarele două exemple sunt echivalente:

//Primul exemplu $rezultat = isset ( $a ) ? $a : 'DefaultValue' ; //Al doilea exemplu dacă ( isset ( $a )) { $rezultat = $a ; } else { $result = 'DefaultValue' ; }

Astfel de constructe sunt adesea folosite pentru a inițializa o variabilă oricum pentru calculele ulterioare (în caz contrar PHP va arunca o eroare la nivel E_NOTICE).

Începând cu versiunea 5.3, a devenit posibil să nu se specifice al doilea parametru al operației. De exemplu, următoarele două intrări sunt echivalente:

$Variable = $_GET [ 'Parametru' ] ? $_GET [ 'Parametru' ] : 'Valoare implicită' ; $Variable = $_GET [ 'Parametru' ] ?: 'DefaultValue' ;

Visual Basic

În versiunea clasică a Visual Basic , operatorul ternar există ca funcție IIf(Expr, TruePart, FalsePart). Această funcție are o caracteristică: la evaluarea expresiei Expr, se va calcula TruePartși FalsePart, indiferent de rezultatul expresiei: adevărat sau fals. Acest lucru poate duce la rezultate neașteptate și, uneori, la încetinirea execuției codului, dacă valorile returnate sunt apeluri la funcții cu operații lungi.

Dim iCount As Long Public Sub Main () iCount = 1 MsgBox IIf ( 1 = 1 , FuncYes , FuncNo ) „Variabila iCount va conține „3” deoarece ambele funcții vor fi executate MsgBox iCount End Sub Funcție publică FuncYes () As String iCount = iCount + 1 FuncYes = "Yes" End Function Funcție publică FuncNo () As String iCount = iCount + 1 FuncNo = "Nu" End Function

Pentru a înlocui o funcție IIf, puteți rescrie expresia într-o singură linie, dar aceasta nu va fi un analog al funcției, ci va fi doar o formă scurtă a operatorului de ramură

If Expr , atunci TruePart Else FalsePart

Odată cu apariția VB.NET , operatorul ternar familiar a fost inclus în sintaxa limbajului și este scris ca If(Expr, TruePart, FalsePart). Acest operator folosește calcule reduse, spre deosebire de funcția IIf, care este disponibilă și dezvoltatorului pentru compatibilitate cu versiunile anterioare. [5]

Limbajul încorporat 1C

În limbajul de configurare al platformei 1C:Enterprise, operatorul ternar are sintaxa:

?(expresie booleană, expresie 1, expresie 2)

Folosit pe scară largă ca prescurtare pentru constructe Если <логическое выражение> Тогда ... Иначе ... КонецЕсли
În versiunea platformei 7.7, a fost posibil să se utilizeze un operator ternar pe partea dreaptă a unui operator de atribuire [6] .

Haskell

În Haskell , operatorul if branch este o expresie condiționată: expresia else este necesară și trebuie să fie de același tip cu expresia then. De asemenea, în biblioteca standard Data.Bool [7] există o funcție bool care returnează una dintre cele două expresii în funcție de valoarea predicatului.

O operație ternară în forma sa obișnuită poate fi definită ca o funcție infixă prin potrivirea modelelor (tipurile sunt opționale):

( ? ) :: Bool -> a -> a -> a ( ? ) Adevarat a _ = a ( ? ) Fals _ b = b

sau prin orice operațiune de ramificare, cum ar fi dacă sau în cazul:

( ? ) predicat thenExpr elseExpr = if predicat then Expr else elseExpr ( ? ) predicat thenExpr elseExpr = predicat caz de { True -> thenExpr ; _ -> elseExpr }

Deoarece (?) este o funcție infixă (binară), aceasta ia primele 2 argumente și returnează o funcție a unui argument. Pentru a-l aplica celui de-al treilea argument, se folosește aplicația ($):

adevărat ? „atunci” $ „altfel” > „atunci” Fals ? „atunci” $ „altfel” > „altfel”

Note

  1. Operatorul ternar BCPL (pagina 15) (link nu este disponibil) . Manual de referință BCPL . Consultat la 8 mai 2009. Arhivat din original la 31 martie 2012. 
  2. Yu. Yu. Gromov , S. I. Tatarenko . 1.3.12. Operațiune condiționată // Programare în limbaj C / Referent: Profesor A. P. Afanasiev . Arhivat pe 14 aprilie 2009 la Wayback Machine
  3. B. Stroustrup . 7.13. Operare condiționată // Manual de referință C++ . Arhivat pe 12 mai 2009 la Wayback Machine
  4. Operator ?: (C#) // https://msdn.microsoft.com/en-us/library/ty67wk28.aspx Arhivat 2 aprilie 2015 la Wayback Machine
  5. Declarația If (Visual Basic) // https://msdn.microsoft.com/en-us/library/bb513985.aspx Arhivat 2 aprilie 2015 la Wayback Machine
  6. Operator? 1C 7,7 | operator . Consultat la 25 februarie 2018. Arhivat din original pe 25 februarie 2018.
  7. Data.Bool . hackage.haskell.org. Preluat la 29 aprilie 2018. Arhivat din original la 29 aprilie 2018.

Literatură

  • Stefan Randy Davis, Chuck Sfer. Capitolul 4. Operatori // C# 2005 pentru manechine = C# 2005 pentru manechine / editat de T. G. Skovorodnikova. - M.-Sankt Petersburg: Wiley, Dialectics, 2006. - S. 83. - ISBN 5-8459-1068-4 .