素朴な問いの意外な答
以下の Ruby コードを実行すると何が表示されるか?
p -1 ** 0.5
-1 を 0.5 乗するんだから,$(-1)^{0.5} = \sqrt{-1}$ だよね。
つまり,数学的には虚数単位になる。
Ruby って,確かこういうのを Complex で計算してくれるはず。
だから 0.0+1.0i が表示されるんじゃね?
と思ったのだが,実際は -1.0 が表示された。
ええっ?!
なぜこうなった?
ちょっと調べたところ,-1 ** 0.5 という式において,- は整数リテラル -1 の一部ではなく,単項演算子の - と解釈されるようだ。
そして,ここが重要なのだが,単項演算子の - は ** よりも結合の優先順位が低いのである。
だから
(-(1))**(0.5)
ではなく
-((1)**0.5)
という結合になる。
なぜ - が整数リテラルの始まりと解釈されない(そういうふうにパーサーを設計した)のかは謎。
- のあとが数字でなく
-x ** 0.5
とかなら分かるんだけど。
比較
ちなみに
-1 * 0.5
の場合,- は整数リテラル -1 の始まりだろうか,それとも整数リテラル 1 の前に置かれた単項演算子だろうか。
どちらと解釈しても計算結果は変わらないが,Ruby の解釈は前者である。
** か * かだけの違いで全体の解釈がガラッと変わるのは面白い。
演算子として ** の優先順位が高いことともきっと関係があるのだろう。
おわりに
単項演算子も含めて,演算子の結合優先順位は気を付けているが,数字の前の - が単項演算子になるケースについて考えたことは無かった。
盲点だなあ。
関連して,以下の記事もよかったらどうぞ。
Ruby 使いがビビった Rust の -1_i32.abs() - Qiita