Edited at

【PHP】案外知られてないかもしれないintegerにキャストした際の挙動まとめ


公式リファレンスマニュアルを今一度読んで仕様を把握する

案外知られてない?みたいな感じだったので、なかなかに引っかかると厄介な挙動3種を以下に1再まとめましたので、

知らなかった方はこの機会に公式リファレンスマニュアルを読んでみてください

という記事です。


未知の端数をintegerにキャストすると予期しない結果になる

echo (int) ( (0.1 + 0.7) * 10 );

echo "\n------------------------\n";
echo (float) ( (0.1 + 0.7) * 10 );

以下実行結果

7

------------------------
8

以下float の精度に関する注意から引用


さらに、十進数では正確な小数で表せる有理数、たとえば 0.1 や 0.7 は、 二進数の浮動小数点数としては正確に表現できません。 これは、仮数部をいくら大きくしても同じです。 したがって、それを内部的な二進数表現に変換する際には、どうしても多少精度が落ちてしまいます。 その結果、不思議な結果を引き起こすことがあります。たとえば、 floor((0.1+0.7)*10) の結果はたいてい 7 となるでしょう。おそらくは 8 を想定していらっしゃるでしょうが、そのようにはなりません。 これは、(この計算結果の) 内部的な値が 7.9999999999999991118... のようになっているからです。

よって、小数の最後の桁を信用してはいけませんし、 小数を直接比較して等しいかどうかを調べてはいけません。より高い精度が必要な場合には、 任意精度数学関数または gmp 関数を代わりに使用してください。


詳細は上記のリンク先に書いてあるので読んでおきましょう


キャストは先頭が数字で始まる文字列のみ機能する

echo (int) "5txt";

echo "\n------------------------\n";
echo (int) "before5txt";
echo "\n------------------------\n";
echo (int) "53txt";
echo "\n------------------------\n";
echo (int) "53txt534text";
echo "\n------------------------\n";

以下実行結果

5

------------------------
0
------------------------
53
------------------------
53
------------------------

見ての通り、先頭が数字で始まる文字列の数字部分しかキャストされないので、注意が必要です。

文字列から整数への変換に関しては以下を参考にしてください


数値リテラルの先頭「0」は「8進数」と認識されるが文字列の場合その限りではない

echo "\n[先頭0の数値]------------------------\n\n";

var_dump(0123);

echo "\n[先頭0の文字列]------------------------\n\n";

var_dump("0123" + 0);

以下実行結果

[先頭0の数値]------------------------

int(83)

[先頭0の文字列]------------------------

int(123)

数値の先頭に0を付けると8進数として認識され、83(3*1) + (2*8) + (1*64) + (0*512))と出力されます。

しかし、文字列で先頭に0を付け、integerにキャストして出力すると123と、8進数と認識されずにそのまま出力されるので注意する必要があります。


おわり


  • 何か間違いあれば教えて欲しいです(自分も完全に理解しているわけじゃないので・・・)

  • ↑で書いた処理をまとめたやつ置いときます → https://3v4l.org/Wql54


参考





  1. 公式リファレンスマニュアルに全部かいてあることなので