==で文字列同士を数値として比較する条件

追記(2008/5/9):本記事をもとに、先日PHP-doc MLで用語の統一の提案を投げてみたところ、すんなり提案が通った形で、日本語マニュアル上で用語の統一がされました。本記事で指摘している「数値文字列」という単語は現在ではマニュアルから消えています。本記事の内容は修正せずに残しておきますが、読む際にはご注意ください。そしてPHP-doc MLの議論に参加している皆様、ありがとうございます。特にm-takagiさんには足を向けて眠れません(なんだか取って付けた感が漂う文章ですね…いやいや、本気でそう思ってますよ!)。

あけましておめでとうございます、hnwです。もう1月も半分すぎてしまいましたが、まだ年賀状が売っているそうですから、きっとおめでたいのでしょう。さて、今回はPHPの==による文字列同士の比較についての話題です。

PHPの==演算子は両辺が文字列同士の場合に、両辺ともis_numeric()がtrueになるような文字列だった場合には数値として比較し、それ以外なら文字列として比較します。

<?php
  if ("0xff" == "0XFF") {
    echo "true 1\n";
  }
  if (is_numeric("0xff") && is_numeric("0XFF")) {
    echo "true 2\n";
  }
  if ("xff" == "XFF") {
    echo "true 3\n";
  }
  if (is_numeric("xff") && is_numeric("XFF")) {
    echo "true 4\n";
  }

上記スクリプトを実行するとtrue 1とtrue 2の2行が帰ってきますので、上に書いた挙動に矛盾は無いことがわかります。また、PHPのCソースコードを読めば、is_numeric()関数と==演算子とで同じ処理を経由しており、上に書いた通りに実装されていることもわかります。

しかし、マニュアル上に書いてあるならともかく、特定のバージョンのソースコードを読んでそうなっていたというのでは、そのバージョンで偶然そうなっていただけという可能性もあるわけです。マニュアル上にその根拠が無いのかな、ということが私は以前から気になっていましたが、それらしい記述を見つけたので紹介します。

まずは日本語版のリファレンスマニュアルを読み直してみましょう。

数値形式の文字列を比較する場合、それは整数として比較されます。

PHPマニュアル - 比較演算子

数値形式って何だろう?というのが私の長い間の疑問でしたが、英語版マニュアルの対応する文章を見て疑問が解けました。

If you compare two numerical strings, they are compared as integers.

PHP: Comparison Operators - Manual

なるほど、両者が「numerical string」だったら整数として比較するんだそうです。ここでis_numeric関数の説明も見てみました。

is_numeric — Finds whether a variable is a number or a numeric string

PHP: is_numeric - Manual

is_numeric()というのは、number(整数または浮動小数点数)か、numeric stringだったらtrueを返す関数なんですね。これらの記述から、「==で比較する両辺が文字列だった場合、両辺ともis_numeric()がtrueを返すようなら数字として比較します」というのはマニュアルから読み取れると言えそうです。

もっとも、マニュアル上の記述では「compared as integer」とあるのに対し、実際には文字列”0.01″と”1e-2″などは浮動小数点数として比較しますので、マニュアルに事実が書いてあるわけでも無いんですよね…。まあ、反例が出てくるまでは「compared as number」が仕様という風に理解しておきましょう。

そんなわけで、「==演算子は両辺が文字列同士の場合に、両辺ともis_numeric()がtrueになるような文字列だった場合には数値として比較する」というのはマニュアルに書いてあることになりました。以前のis_numeric()を解説するエントリは「==」が文字列同士を数値比較する条件の説明にもなっているわけです。ご活用ください。

コメント / トラックバック 1 件

#1 講習会「PHPの未定義値と値の検査」を開催しました 2008/05/09 23:13

[...] PHPの比較演算子とis_numeric関数の関係や、数値形式の文字列とは何か、といった話題は時間の都合で話せませんでした。このあたりは私が過去に「==で文字列同士を数値として比較する条件」という記事を書いていますので、興味のある方はご覧下さい。 [...]

コメントする