Benefits of Ternary Operator VS. If Statement

Benefits of ternary operator vs. if statement

Performance

The ternary operator shouldn't differ in performance from a well-written equivalent if/else statement... they may well resolve to the same representation in the Abstract Syntax Tree, undergo the same optimisations etc..

Things you can only do with ? :

If you're initialising a constant or reference, or working out which value to use inside a member initialisation list, then if/else statements can't be used but ? : can be:

const int x = f() ? 10 : 2;

X::X() : n_(n > 0 ? 2 * n : 0) { }

Factoring for concise code

Keys reasons to use ? : include localisation, and avoiding redundantly repeating other parts of the same statements/function-calls, for example:

if (condition)
return x;
else
return y;

...is only preferable to...

return condition ? x : y;

...on readability grounds if dealing with very inexperienced programmers, or some of the terms are complicated enough that the ? : structure gets lost in the noise. In more complex cases like:

fn(condition1 ? t1 : f1, condition2 ? t2 : f2, condition3 ? t3 : f3);

An equivalent if/else:

if (condition1)
if (condition2)
if (condition3)
fn(t1, t2, t3);
else
fn(t1, t2, f3);
else if (condition3)
fn(t1, f2, t3);
else
fn(t1, f2, f3);
else
if (condition2)
...etc...

That's a lot of extra function calls that the compiler may or may not optimise away.

Further, ? allows you to select an object, then use a member thereof:

(f() ? a : b).fn(g() ? c : d).field_name);

The equivalent if/else would be:

if (f())
if (g())
x.fn(c.field_name);
else
x.fn(d.field_name);
else
if (g())
y.fn(c.field_name);
else
y.fn(d.field_name);

Can't named temporaries improve the if/else monstrosity above?

If the expressions t1, f1, t2 etc. are too verbose to type repeatedly, creating named temporaries may help, but then:

  • To get performance matching ? : you may need to use std::move, except when the same temporary is passed to two && parameters in the function called: then you must avoid it. That's more complex and error-prone.

  • c ? x : y evaluates c then either but not both of x and y, which makes it safe to say test a pointer isn't nullptr before using it, while providing some fallback value/behaviour. The code only gets the side effects of whichever of x and y is actually selected. With named temporaries, you may need if / else around or ? : inside their initialisation to prevent unwanted code executing, or code executing more often than desired.

Functional difference: unifying result type

Consider:

void is(int) { std::cout << "int\n"; }
void is(double) { std::cout << "double\n"; }

void f(bool expr)
{
is(expr ? 1 : 2.0);

if (expr)
is(1);
else
is(2.0);
}

In the conditional operator version above, 1 undergoes a Standard Conversion to double so that the type matched 2.0, meaning the is(double) overload is called even for the true/1 situation. The if/else statement doesn't trigger this conversion: the true/1 branch calls is(int).

You can't use expressions with an overall type of void in a conditional operator either, whereas they're valid in statements under an if/else.

Emphasis: value-selection before/after action needing values

There's a different emphasis:

An if/else statement emphasises the branching first and what's to be done is secondary, while a ternary operator emphasises what's to be done over the selection of the values to do it with.

In different situations, either may better reflect the programmer's "natural" perspective on the code and make it easier to understand, verify and maintain. You may find yourself selecting one over the other based on the order in which you consider these factors when writing the code - if you've launched into "doing something" then find you might use one of a couple (or few) values to do it with, ? : is the least disruptive way to express that and continue your coding "flow".

advantage of ternary operator over if else?

If you look at the disassembly of both approaches, they're generally the same on any modern compiler I know of. The ternary operator is just a compact form of writing the same thing.

Here's an example using gcc 4.2.1 on Mac OS X:

With if/else:

int x = 1;
int y = 2;
int z;

if (x < y)
{
z = 3;
}
else
{
z = 4;
}

With the ternary operator:

int x = 1;
int y = 2;
int z = (x < y) ? 3 : 4;

If you run gcc -S test.c on both of these, you get this assembly for the if/else version:

    movl    $1, -16(%rbp)
movl $2, -20(%rbp)
movl -16(%rbp), %eax
movl -20(%rbp), %ecx
cmpl %ecx, %eax
jge LBB1_2
movl $3, -12(%rbp)
jmp LBB1_3
LBB1_2:
movl $4, -12(%rbp)

and this for the ternary operator version:

    movl    $1, -12(%rbp)
movl $2, -16(%rbp)
movl -12(%rbp), %eax
movl -16(%rbp), %ecx
cmpl %ecx, %eax
jge LBB1_2
movl $3, -20(%rbp)
jmp LBB1_3
LBB1_2:
movl $4, -20(%rbp)

The register offsets are different, but functionally, the code does the same thing. It adds two literals to two different registers, then compares and jumps based on the result of the comparison.

Is ternary operator less efficient than an if statement that sets a different value to a variable

In your case, your ternary operation and your if statement are not the same, since you don't have an else statement after if, so it only checks whether a>b.

If you are interested in the question about the performance difference in case of semantically equal Ternary operation and if-else block, then the answer is No, there is no much of the difference. Ternary Operator is just a syntactic sugar of writing if-else.

Here is the bytecode comparison in the simplest Java program, with only one (an entry-point) main method, where in first case I implement Ternary Operator, and in the second one - if-else statement.

 //First example, having Ternary Operator
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iconst_1
3: istore_2
4: iload_1
5: iload_2
6: if_icmple 13
9: iload_2
10: goto 14
13: iload_1
14: istore_1
15: return
}


//Second Example, having if-else alternative
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iconst_1
3: istore_2
4: iload_1
5: iload_2
6: if_icmple 14
9: iload_2
10: istore_1
11: goto 16
14: iload_1
15: istore_1
16: return
}

Ternary operator ?: vs if...else

Depends on your compiler, but on any modern compiler there is generally no difference. It's something you shouldn't worry about. Concentrate on the maintainability of your code.

Ternary ? operator vs the conventional If-else operator in c#

I ran 100 million Ternary Operators and 100 million If-Else statements and recorded the performance of each. Here is the code:

Stopwatch s = new Stopwatch();
// System.Diagnostics Stopwatch
int test = 0;
s.Start();
for(int a = 0; a < 100000000; a++)
test = a % 50 == 0 ? 1 : 2;
s.Stop();

s.Restart();
for(int b = 0; b < 100000000; b++)
{
if(b % 50 == 0)
test = 1;
else
test = 2;
}
s.Stop();

Here is the results (ran on an Intel Atom 1.66ghz with 1gb ram and I know, it sucks):

  • Ternary Operator: 5986 milliseconds or 0.00000005986 seconds per each operator.

  • If-Else: 5667 milliseconds or 0.00000005667 seconds per each statement.

Don't forget that I ran 100 million of them, and I don't think 0.00000000319 seconds difference between the two matters that much.

Benefits of using the conditional ?: (ternary) operator

I would basically recommend using it only when the resulting statement is extremely short and represents a significant increase in conciseness over the if/else equivalent without sacrificing readability.

Good example:

int result = Check() ? 1 : 0;

Bad example:

int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0;

nested ternary operator vs nested if else, which is better in readability purpose

Just reformatting your code makes it quite clear:

ColorEnum color = 
opacity == Opacity.FIVE ? ColorEnum.BLACK
: opacity == Opacity.TEN ? ColorEnum.WHITE
: opacity == Opacity.FIFTY ? ColorEnum.RED
: opacity == Opacity.TWENTY ? ColorEnum.BLUE
: opacity == Opacity.FIFTEEN ? ColorEnum.PURPLE
: null;

LISP adopts the cond construct which has both the same structure and the same semantics, and is considered good practice. As an aside, Clojure also supports a form which tests the value of a single expression with a single predicate applied to different values (one for each clause) and calls it condp—that would be a perfect match for your use case.

The idiom with the ternary operator has the advantage over an if-else cascade for being an expression so you need only a single statement to assign it to the variable. if-else will force you to pull the assignment into each then clause, introducing more boilerplate and more opportunity to fail on correctness.

A switch statement could also be considered as an alternative, but it would have the following deficiencies:

  • like if-else, it is not an expression;

  • you are restricted to just different constant values of a single expression (the type of the expression being quite constrained, too).

  • it's prone to bugs due to the boilerplate break missing somewhere.

Why would you choose to use the ternary operator (?:) over a traditional if..else block?

As you say, is a compressed if-then-else, so it must be compiled to the same instructions with regards of the comparisons.

The real difference is that it selects a final result. Really, just syntactic sugar that improves readability.

Compare:

int val = (foobar == true) ? 500 : 1000 ;

vs:

int val = 0;
if (foobar == true)
{
val = 500;
} else {
val = 1000;
}

It can be argued that it is just a matter of style, thus subjective. But, the legibility becomes even greater when you have a more complex decision tree, such as:

int val = (flag01 == true) ? 
(flag02 == true ) ? 100 : 200 :
(flag03 == true ) ? 300 : 400 ;

You can chain together many decisions in one place instead of writing a bunch of nested if-then-else clauses:

 int val = 0;
if (flag01 == true)
{
if (flag02 == true)
{
val = 100;
} else {
val = 200;
}
} else {
if (flag03 == true)
{
val = 300;
} else {
val = 400;
}
}

This is somewhat following a code pattern called method chaining.



Related Topics



Leave a reply



Submit