TRASH-NEWS 俗・PHPで文字列が(純粋に)数値かどうかを判別する方法

順路
  1. ホーム
  2. 2009年
  3. 11月
  4. 25日
  5. この記事 [現在地]
Search?
お知らせ
社会人近況 (2008/09/07 0:00)
配属されてからこの方、ほぼ毎日終電での帰宅が続いているうえに毎週泊まりがけの出張が入っているため、1週間に1回か2回更新できればマシといった状況です。実はまだTRASH-NEWSは概要ページもリンクコーナーもろくに作っていないような有様なんですけれども、気づけばそろそろ1周年+すでに50万ヒット。……なんだこのえもいわれぬグダグダ感は……。とりあえずヴェスペリア堪能してから考えますね。
1 2 3

俗・PHPで文字列が(純粋に)数値かどうかを判別する方法

関連ページ
  1. PHP
  2. 自作関数
TRASH-NEWSは
いろいろと紙一重なニュースサイトです
初出時刻
2009年11月25日 01時09分 投稿
最終更新時刻
2009年11月25日 23時05分 改訂
  • この記事をはてブする
  • Yahoo!ブックマークに登録

PHPで文字列が(純粋に)数値かどうかを判別する方法、の続きです。

上記の記事冒頭。
× PHPではその判別の方法として"is_int"と"is_numeric"の2種類がデフォルトで用意されています。
PHPではその判別の方法として"is_int"と"is_numeric"、"ctype_digit"の3種類がデフォルトで用意されています。

ctype_digit : "文字列が10進数字か"を判別する関数。ただしstringを指定したときのみ正常に動き、intを指定すると常にFALSEという利用者軽視の困った仕様。

ctype 関数は、正規表現よりもつねに好ましく、さらに str_* および is_* のような いくつかの等価な関数よりも好ましいことに注意してください。 これは、ctype 関数がネーティブな C ライブラリを使用しており、処理が著しく 高速であるためです。 (PHP : ctype関数)

とのこと by PHPの中の人。

ひょっとしてctype_digitを使えばよいのではないかというすごくいまさらなアイディアが脳内を。このctype_digit関数、歴史的に残念なあやまちはあるものの、C言語的な意味でネイティブな処理ならこれに勝る挙動はありません。is_*関数より好ましいとか名指しで書かれちゃってますしね!

ひとつネックである『int指定時に常にFALSE』という仕様も、is_intと組み合わせれば良いわけで、これで隙はなくなったなァァァ!!!!

と……でもこれって、文字列の端から桁の概念ナシに1文字ずつ数字かどうか確認していくみたいですから"01234"でもTRUEなんですよね……。たとえばformでユーザーから数値の入力を求めたときに01234なんて文字列が送られてきたら、これは『問題はないけど間違ってはいる』レベルであり、個人的にはエラーを返したい。でもctype_digit+is_intじゃダメ。数字は数字ということでOKになってしまう。いやだから数字かどうかではなく、数値かどうかを知りたいのに。ということはやはり『1文字目が0だとFALSEを返す』あるいは『数値化したとき元の文字列とstringとして比較して異なるとFALSEを返す(ややこしい)』仕様がほしい。と、なると……ああ、やっぱり正規表現か先述の記事で示した以下のコードが有用ということに。


function Is_NumStr($String){
	if($String && strval($String) === strval(abs(intval($String))) && !is_bool($String)){
		return TRUE;
	}else{
		return FALSE;
	}
}

結局こんな俗っぽい処理が一番なのかなぁ。うーん。うーん……。

----------------------------------------

[追記(1)]
そういえば上記の方法だとintvalの仕様上、システム依存で扱える桁数に制限がかかるというのが問題。だとすると正規表現か、ctype_digitに軍配があがるわけで……まぁでもintの範囲を超えるような数を(たとえ文字列だとしても)扱うことはないし、いいのかな。いや……そこで妥協するくらいならおとなしく正規表現でいいじゃないかという……でもそれだと何かに負けた感じが……ゴゴゴゴゴ。


// [Release ver.1.01]
function Is_NumStr($String){
	if(substr($String,0,1) && (intval($String) > 0) && (is_int($String) or ctype_digit($String))){
		return TRUE;
	}else{
		return FALSE;
	}
}

これでどうだ。substrで頭の1文字が0でないことを確認、intvalと数値比較で負の数でないことを確認、その後の2つの関数でint/stringを問わず数字かどうかを判別。これでようやく、欲していた『文字列が(純粋に)数値かどうか=文字列の見た目が正の整数かどうかをint/stringを問わず判別する』関数が出来上がり。ああややこしかった。

var_dump(Is_NumStr('123')); // TRUE
var_dump(Is_NumStr(123)); // TRUE
var_dump(Is_NumStr('0123ABC'));
var_dump(Is_NumStr('123ABC'));
var_dump(Is_NumStr('123\0ABC'));
var_dump(Is_NumStr('ABC123'));
var_dump(Is_NumStr('000123'));
var_dump(Is_NumStr(0));
var_dump(Is_NumStr('0'));
var_dump(Is_NumStr('-123'));
var_dump(Is_NumStr(-123));
var_dump(Is_NumStr('-12.3'));
var_dump(Is_NumStr('12.3'));
var_dump(Is_NumStr('0.1'));
var_dump(Is_NumStr(0.3));
var_dump(Is_NumStr(.3));
var_dump(Is_NumStr('1.0'));
var_dump(Is_NumStr(''));
var_dump(Is_NumStr(NULL));
var_dump(Is_NumStr(TRUE));
var_dump(Is_NumStr(FALSE));
var_dump(Is_NumStr('123123123123123123123123123123123123123')); // TRUE
var_dump(Is_NumStr(0123)); // TRUE

確認結果もOK。求める仕様は全部満たしました。うん、(たぶん)(もうこれで)いい。なんだかえらくスマートというか、すごく単純すぎる結果に落ち着いてしまってこれもこれで負けた気がする。

----------------------------------------

[追記(2)]
こっそり追記。(intval($String) > 0)の部分で負の数かどうかを判別するように。これがないとIs_NumStr(-123)でTRUEが返ります。追記に伴ってRelease ver.も1.01へアップ。

----------------------------------------

[追記(3)]
var_dump(Is_NumStr(123123123123123123123123123123123123123123123123));
でアウト。考えてみればintvalでダメ。is_intでもそういえばダメ。もうこうなったらdoubleなfloatは関数の頭でハナから弾くとかしないとだめかもね。前記事で触れた10進数以外の数字問題もそうだけど、僕の求めている仕様を完全に満たすにはやっぱりシンプルな書き方だけじゃダメみたい。結局こういうオチか。そもそも非常識な数値をこの関数の引数に指定する機会はあるはずないと言い聞かせるしかなさそうです。

----------------------------------------

[追記(4)]
この記事を書いたのが夜の3時過ぎで、ああやべぇ会社早いしもう寝なきゃなと思いつつ↑の追記(3)を書いたのですが、布団に入ってよくよく考えてみると以下の処理で済むんじゃないかと気づいたんですよ。


// [Release ver.1.1]
function Is_NumStr($String){
	if(!is_bool($String) && substr($String,0,1) && ctype_digit(strval($String))){
		return TRUE;
	}else{
		return FALSE;
	}
}

いま家に帰って確かめてみたら案の定イケました。というか最初から思いついておけよというくらい単純な方法でした。青い鳥ってやつですね。

ちなみに上記のver.1.1の方法でも、preg_match("/^[1-9]\d*$/",$String)といった正規表現でも、doubleのfloatは扱えないようです。strval(123123123123123123123)でそもそも指数表示になるんですね。'123123123123123123123'にはならないみたい。はじめて……知った……。独学者特有の『初歩的なところでのほころび』がこんなところで露呈するとは。

ついでに備忘録として書いておくと、strval(TRUE)は1になる。まぁたしかに1になってくれないと困るんだけど、ちょっと微妙。

サイト内検索
検索する
このサイトについて
  • サイト名 : TRASH-NEWS
  • 分類 : ニュースとネタのサイト
  • ジャンル : 井戸端からアレゲまで
  • もっと詳しく見る
最近の記事
05月23日の記事
  1. ボタンひと押し即生成、『サークルカットジェネレータ』公開開始
04月01日の記事
  1. あの人気シリーズを作れる? 『テイルズオヴメーカー』本日公開
03月27日の記事
  1. 現在の4月のアレ進捗度30%!!
02月21日の記事
  1. 4月のアレで使う【中二なキャラクター】イラストをご提供ください
01月24日の記事
  1. サークル名ジェネレータを作ってみた
01月11日の記事
  1. 新作(※4月のアレではない)のスクリーンショット公開
01月01日の記事
  1. コミケ77(3日目)に行ってきた
12月31日の記事
  1. コミケ77、男は黙って8:00に出発
12月24日の記事
  1. FFXIIIの検索サイトを作ってみました
12月21日の記事
  1. FFXIIIの検索サイトを作ってみている
日刊人気記事ランキング
2010年11月21日のぶん
1
もうやめて下さい!! 泣いてる子もいるんですよ!!
38
2
マリオっぽい自作のゲーム改めしょぼんのアクション公開開始
28
3
FFT-A2のクリア後レビューと感想(ネタバレなし)
17
4
テイルズオブヴェスペリアの感想 【ストーリー・キャラクター編】
14
5
サークル名ジェネレータを作ってみた
12
6
Windows XP SP3インストールで不具合が起きることが発覚
11
7
ついうっかりマリオWiiとグレイセスとFFXIIIとDQVIを予約(以下略)
11
8
○○が可愛すぎて生きるのが辛い
10
9
“マリオっぽいもの”のステージを編集するエディタが公開
9
10
3Dの初音ミクを躍らせるフリーソフトMikuMikuDanceがスゴい
9

2010年11月22日 0時更新

人気記事ランキング

カテゴリ(折畳表示)
ニュース・ネタ
サブカテゴリを開く
俺研究舎
サブカテゴリを開く
お知らせ
サブカテゴリを開く
特集・企画
サブカテゴリを開く
管理人近況
サブカテゴリを開く
カスタムアーキテクチャ
1回めのようこそ!
ゲストさん
  • 文字の大きさ : 12px
  • フォント : MS Pゴシック
  • レイアウト : 3段組
  • カスタムする
カレンダー
2009年11月
«  10月 - 12月  »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
管理人について
管理人 : 八満かシアン
文系なのにエンジニア、なんてこったい(八満のほう)
今頃たぶん聴いている曲
宇宙で恋は☆るるんルーン by ルーンエンジェル隊
月別アーカイブ
2009年
2008年
2007年
最近記事に掲載した画像
サークルカットジェネレータ、公開開始です!!
サークルカットジェネレータ、公開開始です!!
テイルズオヴメーカー偽記事の画像
テイルズオヴメーカー偽記事の画像
シガアレ作ってる、の図
シガアレ作ってる、の図
手描き初音ミク
手描き初音ミク
iPhoneっぽいUIを実際にiPhoneで表示してみて比較
iPhoneっぽいUIを実際にiPhoneで表示してみて比較
画像に関するリンク
ユーティリティ
RSSフィード
ソーシャルブックマーク
  • iGoogle
  • はてなアンテナにTRASH-NEWSを追加する TRASH-NEWSのはてなブックマーク数 この記事を含むはてなブックマーク
サイトプロフィール
Powered by
  • Movable Type 4.1 + [XHTML + CSS + JavaScript] + PHP
  • TRASH-NEWS / Hachiman_Cian 2007-
このページについて
題名
俗・PHPで文字列が(純粋に)数値かどうかを判別する方法
内容
  • PHPで文字列が(純粋に)数値かどうかを判別する方法、の続きです。 上記の記事冒
TRASH-NEWS ロゴ
TRASH-NEWS ロゴ
TRASH-NEWS : http://www.trash-news.net/