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