0==’hoge’の挙動(PHP/Perl/Javascript/Ruby)

この前気付いたのですが,PHPでは何と驚くべきことに0 == ‘hoge’はtrueになります

からくりは文字列と数値を比較すると文字列を数値型にキャストして比較しようとします
PHPの仕様では’14′や’14hoge’は14にキャストされるというように数字から始まっていたらそこが利用されます
しかし’hoge’は数字から始まっていないのでキャストすると0になってしまうのです

これによって0 == ‘hoge’がtrueという直感に反した動きをするわけです
では他の言語ではこんなこと起こりうるのか簡単に見てみたいと思います

Perl

これから紹介する言語の中では最もPHPに近い挙動をします
というのもPHPと同じ結果になります

ただしPerlは==は数値としての比較,eqが文字列としての比較という区別があります
そのため0 == ‘hoge’を比較するとPHPと同じ理由によってtrueにはなりますが,実際にこのようなコードを書くことはありえません
またPerlは最初にuse strict; use warnings;するのが普通ですので,このようなコードを書くと警告が出ます

Javascript

こいつは意外と複雑です
数値型と文字列型を==で比較すると文字列型を数値型にキャストするのは同じです
しかしキャストされた結果がPHPなどとは違います

Javascriptでは数値型にキャストする場合はNumber()を使うのでこれを使って説明すると,Number(‘hoge’)はNaN(Not a Number)に変換されます
NaNは特殊な値で何と比較してもfalseなので(NaN == NaNもfalseになります)なので0 == ‘hoge’はfalseになります

そしてもっと書くとNumber(’14′) = 14となりますが,Number(’14hoge’)はNaNになります
PHPなどに近い挙動をさせたい場合はparseIntを使えばparseInt(’14hoge’)=14になります

ただしparseInt(‘hoge’)はNaNになるので0 == parseInt(‘hoge’)はfalseになります

また文字列から数値型に変換するのにNumberと書くのは長いので+’14′と書くのが普通のようです
+が最初に書かれていると数値型にキャストされます

ただし0 + ‘hoge’は0が文字列にキャストされて’0hoge’が返ってくるので注意が必要です

Ruby

こいつは簡単です
Rubyでは数値型と文字列の暗黙的な変換は行わず,かつ型が違うものは比較できないので0 == ‘hoge’はエラーが出ます
なので型が違うもの同士の比較は明示的にキャストする必要があります

数値型にするには.to_iメソッドを使います
‘hoge’.to_iは0に’14hoge’.to_iは14になりますから0 == ‘hoge’.to_iはtrueになります
が…これはいかにも蛇足感がw

まとめ

明らかにおかしな挙動をするのはPHPだけだと思います
ただPHPとJavascriptには型変換をしない===があります
こちらを使いましょう(特にPHPは)

このエントリーをはてなブックマークに追加