最近老碰到一些因為php做數學運算,發生不痛不癢的小問題。 千里之堤,潰于蟻穴。加個類型轉換,so easy解決了,我覺得不能就這么放過去。 尤其是用php做財務運算或者寫接口運算與強語言對接的同學,可得多加注意。 事情不大,細節決定成敗,仔細研究后門道確實挺多,自己也好好補了一課。 你真的知道php是弱類型語言嗎? 前段時間展開過針對php內核的研究,對php變量底層存儲結構做了細致的了解,但是對不同類型數值的運算過程不甚明白,變量類型的轉變過程。 其實就是我們智能的PHP【類型自動轉換】的問題,這也是PHP作為弱類型語言強大的地方,索性完整研究一下做個總結。(下邊有5個事例,都是很簡單的運算,但你可不一定能說得出其中緣由)
二.過程分析
事例一
先看看我碰到的問題(簡化過),也就是我要寫這篇博客的導火索。$a = '1.11'; $b = '0.11'; var_dump($a);//string(4) "1.11" var_dump($b);//string(4) "0.11" $re = $a - $b; var_dump($re);//float(1) 注意:發生了兩個變化。 1.字符串相減,變成浮點型 2.被減數都是兩位小數,結果為沒有小數【這也是發生bug的地方,app因為顯示時需要小數點后兩位】 同理,當為字符串無小數數字相減,結果為int$a = '11'; $b = '1'; var_dump($a);//string(4) "11" var_dump($b);//string(4) "1" $re = $a - $b; var_dump($re);//int(10) 結論: 1.在PHP底層運算的過程中,會自動進行類型轉換,小數的轉換成float,整數轉換成int。 2.需要對數字有小數點后幾位限制的,記得處理一下。number_format();已經開了頭,那再來聊聊這個類型轉換的事兒唄。事例二 問:下面是true還是falsevar_dump(0123 == 123); var_dump('0123' == 123); var_dump('0123' === 123); 答案是什么呢?? false;true;false 分析: 相信第三個大家很容易猜出時false,因為===時強判斷嘛加入了類型的比較 這里有兩個需要注意的點。一方面是0開的頭整形數字PHP底層會認為是八進制;另一方面是sting轉換成int時會把前邊的0去掉 var_dump(0123 == 123);// false,PHP會默認把0123當作8進制來處理,實際轉化為10進制就是83,顯然這不是相等的。 var_dump('0123' == 123);// true這里php會非常有趣的將’0123’轉換成一個數字而且默認去掉了前面的0也就是123==123 var_dump('0123' === 123);// false很顯然上面的問題已經說過了數字和字符串類型不一致。 結論: 1. 0開頭的整形數字PHP會當作八進制來處理 2. 同事例一的結論1,字符串在運算時會自動做類型轉換,而且會把前邊的0去掉事例三 下面$x的結果是多少:$x = NULL; if ('0xFF' == 255) { $x = (int)'0xFF'; } $x = ? 答案是什么呢?? $x=0而不是255 注意點: 首先'oxFF' == 255我們好判斷,會進行轉換將16進制數字轉換成10進制數字,0xff = 255。PHP使用is_numeric_string 判斷字符串是否包含十六進制數字然后進行轉換。 但是$x = (int)'0xFF';是否也會變成255呢?顯然不是,將一個字符串進行強制類型轉換實際上用的是convert_to_long,它實際上是將字符串從左向右進行轉換,遇到非數字字符則停止。因此0xFF到x就停止了。所以$x=0 結論: 1.0開頭的整形數字PHP會當作十六進制來處理 2. string->int的過程,是將字符串從左向右進行轉換,遇到非數字字符則停止。事例四 經過下面的運算 $x的值應該是多少?$x = 3 + "15%" + "$25" 答案是什么呢?? 18 注意點:其實就是前邊的所提到的點。3+15+0=18(0時因為從左往右取數字嘛,遇到非數字停止,沒有當然為0)事例五(無關類型轉換,但也很有意思)$a = true && false; var_dump($a); $a = true and false; var_dump($a); 答案是什么呢?? false;true為什么呢?是對運算符優先級的一個理解,哈哈,提醒到這里自己去查查吧~
本文地址:http://blog.csdn.net/ty_hf/article/details/54930120
新聞熱點
疑難解答
圖片精選