ラベル の投稿を表示しています。 すべての投稿を表示
ラベル の投稿を表示しています。 すべての投稿を表示

2013年3月17日日曜日

おかしな挙動?

最近になってPHPでどうしても理解できない挙動をする式を見つけました。
以下、そのサンプルコードと実行結果です。

サンプルコード 実行結果
1211
パターン1とパターン3、パターン2とパターン4が同じ結果になると思ったのですが、そうはなりませんでした。
パターン4の条件式ですが、普通に解釈すると右から解釈するので
$aに0が代入され、その$aをbooleanにキャストするのでFALSEになる筈なのですが…?
原因はわかりませんが、(bool)の型キャスト部分を消すと実行結果は1212と予想通りになります。
ともあれ、三項演算子と型キャストを同時に使うのは避けたほうがよさそうです。

int型について考える

int型について考えます。
int型と言えば"整数型"ですが、整数の表現は様々なものがあります。
以下、その表現方法です。
  • 123      // 正の整数
  • -123     // 負の整数
  • 0b1011 // 2進数(先頭に"0b"をつける)
  • 0123    // 8進数(先頭に"0"をつける)
  • 0x123  // 16進数(先頭に"0x"をつける)
いかがでしょうか。一概に整数と言っても表現方法は様々ですね。

皆さんは普段は10進数しか使わないのではないでしょうか。
ここで一つ、2進数の有用な使い方をご紹介します。

以下、2つのサンプルコードをご覧ください。

サンプルコード
実行結果
FLAG1
FLAG3
FLAG5
サンプルコード 実行結果
FLAG1
FLAG3
FLAG5
と、このように5つの変数に分けて持っていたフラグが一つの変数にまとまりました。
結局フラグ比較する時に特定の2進数と比較しないといけないため複雑になっている気もしますが…。
このような扱い方もあります。という程度の紹介でした。
忘れずにベンチマークです。

サンプルコード 実行結果
BenchMark 1     average:0.0023561954498291
BenchMark 2     average:0.0024597406387329
可読性の問題もありますし素直に複数の変数にフラグを持ったほうがいいですね。

2013年3月16日土曜日

boolean型について考える

boolean型は真と偽の2つの値だけをとる最も単純な型です。
それゆえに、私を含めて多くの方はこの型を多用しているのではないでしょうか。
今回はそんなboolean型について考えます。

まずはbooleanで偽と扱われる値について
  • boolean の FALSE
  • integer の 0 (ゼロ)
  • float の 0.0 (ゼロ)
  • 空の文字列、 および文字列の "0"
  • 要素の数がゼロである 配列
  • メンバ変数の数がゼロである オブジェクト (PHP 4のみ)
  • 特別な値 NULL (値がセットされていない変数を含む)
  • 空のタグから作成された SimpleXML オブジェクト 
ここで注目すべき点はintegerおよび文字列の0です。
つまり、変数の値が0でないことが保証できればboolean型で空文字のチェックができます。

サンプルコード 実行結果
NULL : bool(false)
"" : bool(false)
"0" : bool(false)
"a" : bool(true)
0 : bool(false)
1 : bool(true)
+1 : bool(true)
-1 : bool(true)
0x0A : bool(true)
012 : bool(true)
0.1 : bool(true)
1e3 : bool(true)
1e-3 : bool(true)
array("") : bool(false)
array("a") : bool(true)
array(array("a")) : bool(true)
TRUE : bool(true)
FALSE : bool(false)
object : bool(true)
fopen : bool(true)
では、肝心のベンチマークを取ってみましょう。

サンプルコード 実行結果
BenchMark 1     average:0.0022930383682251
BenchMark 2     average:0.0024604082107544
そして、最後に注意点をひとつ。未定義の変数を判別しようとしますと…。

サンプルコード 実行結果
Notice: Undefined variable: x in C:\xampp\htdocs\test.php on line 2
と、Noticeが出てしまいます。
この場合は素直にissetやemptyを使ったほうが良いでしょう。

2013年3月15日金曜日

intからfloatへ

PHPの型は動的なので意図せずに型が変わってしまう場合があります。
今回はその一例をメモいたします。

サンプルコード 実行結果
int(2147483647)
float(2147483648)
int(-2147483648)
と、このような現象が起こる場合もあります。
以上、備忘録でした。

2013年3月13日水曜日

タイプヒンティング

今更ながらPHPのマニュアルには有益な情報が沢山載っていることに気づきました。
関数を調べるときにだけマニュアルを見るくらいでしたが、それでは勿体無いですね。

遅まきながら知った情報として、タイプヒンティングがあります。

サンプルコードはマニュアルに載っているので省略し増ますが、要するに関数の引数の型を指定できるという内容です。
残念ながらintstring といったスカラー型には使えませんが、有効に使えば関数内での引数チェックの手間が省略できそうですね。

2013年3月12日火曜日

Validation その3

今回は数値についてです。これが厄介です。
普通、数値と言いますと自然数を想定してコーディングする方が多いかと思います。
ですが、プログラム上で表現できる数値には様々な種類があります。



  • 符号の有無(+-)
  • 基数の違い(2進数、8進数、10進数、16進数)
  • int型の範囲(32ビット符号付ですと-2147483648~2147483647)を超える数値
  • 浮動小数点
  • 指数表現

これらの値について、使用しても良いかどうかを考慮しつつコーディングをしていかなければなりません。
今回は数値の中でも最も頻繁に使われる形式、Integerについて考えていきましょう。

チェックの手順

1. 引数がint型かどうかを調べる
int型ならreturn

2. int型でなければ次の可能性が上げられる
2.1 float型
2.2 string型の数値文字列
2.3 数値とは全く関係のない値

3. int型にキャストする際に注意すべき点
3.1 int型を超えた値でないか
超えていたらNULLを返す
超えていなければint型にキャストした値を返す

4. 数値とは全く関係ない値の場合
NULLを返す

サンプルコード 実行結果
NULL : NULL
"" : NULL
"a" : NULL
0 : int(0)
1 : int(1)
+1 : int(1)
-1 : int(-1)
0x0A : int(10)
012 : int(10)
0.1 : int(0)
1e3 : int(1000)
1e-3 : int(0)
array("") : NULL
array("a") : NULL
array(array("a")) : NULL
TRUE : NULL
FALSE : NULL
object : NULL
fopen : NULL
成功です。以降、数値のチェックをする際はこの関数を使って入力チェックを行っていきます。

Validation その2

今回は配列の判定です。これも簡単ですね。

取得したい値と弾きたい値の仕様について考えましょう。

取得したい値

  • array
弾きたい値
  • NULL
  • integer
  • float
  • string
  • boolean
  • object
  • resouce

サンプルコード 実行結果
NULL : array(0) {
}
"" : array(0) {
}
"a" : array(0) {
}
0 : array(0) {
}
1 : array(0) {
}
+1 : array(0) {
}
-1 : array(0) {
}
0x0A : array(0) {
}
012 : array(0) {
}
0.1 : array(0) {
}
1e3 : array(0) {
}
1e-3 : array(0) {
}
array("") : array(0) {
}
array("a") : array(1) {
  [0]=>
  string(1) "a"
}
array(array("a")) : array(1) {
  [0]=>
  array(1) {
    [0]=>
    string(1) "a"
  }
}
TRUE : array(0) {
}
FALSE : array(0) {
}
object : array(0) {
}
fopen : array(0) {
}
ちなみに、実際に使用するときは以下のように判別して使用します。

Validation その1

スクリプトを書いていて気を使うところは変数のバリデーションです。
今回はその中で、scalar値かどうかの判別について考えたいと思います。

まず、取得したい値と弾きたい値の仕様について考えます。
取得したい値
  • integer
  • float
  • string
  • boolean

弾きたい値
  • NULL
  • array
  • object
  • resouce

というわけで、実装した関数はこうなりました。

サンプルコード

実行結果
NULL : string(0) ""
"" : string(0) ""
"a" : string(1) "a"
0 : int(0)
1 : int(1)
+1 : int(1)
-1 : int(-1)
0x0A : int(10)
012 : int(10)
0.1 : float(0.1)
1e3 : float(1000)
1e-3 : float(0.001)
array("") : string(0) ""
array("a") : string(0) ""
array(array("a")) : string(0) ""
TRUE : bool(true)
FALSE : bool(false)
object : string(0) ""
fopen : string(0) ""

上記の通り、特に問題なさそうです。
スカラー値を取得したいときはこの関数を使用していきたいと思います。