The Ternary Operator

The ternary operator (the question mark and colon in the expression a ? b: c) is a tricky one.  It’s use is relatively uncommon, but it’s present in many programming languages, and sometimes it drastically simplifies a conditional assignment.  I bring it up because it was in the first version I saw of the GAA objective function, and it was doing something it shouldn’t have been.  Before I took up the GAA problem, some of the work involved allowing a 3 percent constraint violation.  This was still present in the objective function when I got my hands on it, although we no longer wanted to allow a 3 percent constraint violation.

Here’s what it looked like:


constr[0] = CV_TOTAL > 0.03 ? CV_TOTAL : 0.0;

What it does is assign CV_TOTAL to constr[0] only if CV_TOTAL is greater than 0.03, and otherwise it assigns 0 to constr[0].  It works this way because in general, the expression a ? b : c evaluates to b if a is true, and to c if a is false. So writing d = a ? b : c is a shorthand way of saying, “assign b to d if a is true, and assign c to d if a is false.”  And what it does in this case is allow 3% constraint violation.

My advice: there’s nothing wrong with using the ternary operator, but don’t be stingy with your comments.  Writing it like this could save you a lot of time:


constr[0] = CV_TOTAL > 0.03 ? CV_TOTAL : 0.0; // allow 3% constraint violation!

Of the  languages that I’ve used, the ternary operator shows up in this form in C, C++, Java, and Ruby.

Advertisements

3 thoughts on “The Ternary Operator

  1. Thanks for the interesting post. Why do people use this operator? I realize that it’s a short amount of code, but is it also faster than explicitly writing out the if statement?

  2. Faster? I think it’s probably equivalent.
    But its concise, I prefer using this when a, b and c are single statements.

    It’s also very helpful when used in-line.
    ie. I often use it within long chains of concatenations…
    //this is Perl
    my $out =
    “blah blah” .
    ( $row->{‘something’} ? ‘ Something:’ . $row->{‘something’} : ”) .
    “more blah blah”;

    so when there is no ‘something’ it just concatenates an empty string ”

  3. As far as speed goes, I compiled this code to assembly (gcc -S) with no optimization flags turned on:

    int main(int argc, char** argv){
    int a=0, b=1;
    int d, e;

    if(a < 4){d=b;}
    else{d=0;}

    e=15;

    d= a<4 ? b : 0;

    return 0;
    }

    The two conditional assignments look like this:

    cmpl $3, -16(%rbp)
    jg .L2
    movl -12(%rbp), %eax
    movl %eax, -8(%rbp)
    jmp .L3
    .L2:
    movl $0, -8(%rbp)
    .L3:

    movl $15, -4(%rbp)

    cmpl $3, -16(%rbp)
    jg .L4
    movl -12(%rbp), %eax
    jmp .L5
    .L4:
    movl $0, %eax
    .L5:
    movl %eax, -8(%rbp)

    I put e=15 in there just to serve as a marker to split up the two assignments. It's interesting how they take slightly different approaches to get the same result. The if-else does the comparison, then copies b to the register EAX, and from EAX to d if it's true, and just writes 0 to d if it's false. The ternary operator does the comparison, then copies b to EAX if it's true, and puts 0 in EAX if it's false. Then it writes EAX to d regardless. So for the true case, the ternary operator and the if-else do exactly the same thing in a slightly different order, and in the false case, the ternary operator does one extra operation: putting 0 in EAX.

    I'd say that if you turn on optimization, it probably comes out the same either way. (For this specific program, the optimizer recognizes that it doesn't do anything and optimizes the whole thing away.)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s