首頁  >  文章  >  後端開發  >  PHP開發人員基本上都會犯錯的運算詳解

PHP開發人員基本上都會犯錯的運算詳解

黄舟
黄舟原創
2018-05-29 10:27:561517瀏覽

一.前言

最近老碰到一些因為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還是false

    var_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

  为什么呢?是对运算符优先级的一个理解,哈哈,提醒到这里自己去查查吧~

事例六

  $arr = array(0,1,2,3);
  foreach ($arr as $key => $value) {}
  var_dump(current($arr));//最后指针停留在数组结尾,取不到值了输出false

  $arr = array(0,1,2,3);
  foreach ($arr as $key => $value) { 
  //$arr其实是进行了一次传值,用的是$arr_copy 
        $arr[$key] = $value;//进行了改值,则发生分离现象
  }
  var_dump(current($arr));//输出1

输出false 与 1;(PHP5.6环境下,php7已经做了修改);

那这个又是为什么呢?【和PHP内核有关,变量分离改变】

以上是PHP開發人員基本上都會犯錯的運算詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn