前稿をアップしたら、思いの外反響が大きく、facebook、ニコニコ生放送で興味深いレスポンスをいただいたので、ここで紹介する。
a>b を使った解答
C の関係演算子は成立すると1を、不成立だと0を返すので、以下のように記述できる。
return (a>b)*a + (a<=b)*b;
すばらしい。
この解法は清水悠氏らに教えていただいた。
&& を使った解答
C の exp1 && exp2 文は、exp1 が真の時のみ exp2 が評価される。この性質を使うと、以下のように書ける。
return a < b && (a = b), a;
この解答は条件分岐命令を生成するので不可だと考えたのだが、最新のコンパイラ(VS2013, gcc の最新のやつ)でコンパイルすると、なんと cmovecc 命令が生成されるのだ。
cmovecc 命令は、条件が成立している場合のみ move 命令を実行するというもので、分岐をすることが無いので、パイプラインがリセットされることが無いという優れものの命令だ。
実はおいらは x86 にこんな命令が追加されていることを知らなかった。
この解法、cmovessのことも清水悠氏に教えていただいた。大変勉強になりました。thx
abs(a-b) を使った解答
(a+b)+(a-b) = 2a, (a+b)+(b-a) = 2b なので、以下のようにも書ける
return ((a+b)+abs(a-b)) / 2;
ただし、この書き方はオーバーフローする場合(例えば、0x80000000 が指定された場合)に正しい答えを返さないという問題がある。
この解法は きしだ氏 に教えていただきました。
レスポンスを下さった方々、ありがとうございました。
追記(2014/12/04):さらに別解を教えていただきました。こちらを参照。