PHPでは、 IP2long()関数は、IPアドレス(たとえば、 192.168.1.1 )を長い整数に変換するために広く使用されています。通常、この関数は、特にIPアドレスを保存または比較する必要がある場合に、ネットワークプログラミングで使用されます。これは、IPアドレスを整数に効果的に変換して簡単に処理できるようにすることができます。しかし、これらの変換された整数に対して数学的操作を直接実行できますか?この記事では、この問題について詳しく説明し、その特定の状況を分析します。
PHPのIP2long()関数は、IPv4アドレスを32ビットの符号なし整数に変換します。 IPv4アドレスは4つのバイトで構成され、 IP2long()はこれらのバイトを整数に整数に変換することで達成されます。
たとえば、 IP2long()関数を呼び出すIPアドレス192.168.1.1があるとします。
<span><span><span class="hljs-variable">$ip</span></span><span> = </span><span><span class="hljs-string">'192.168.1.1'</span></span><span>;
</span><span><span class="hljs-variable">$long</span></span><span> = </span><span><span class="hljs-title function_ invoke__">ip2long</span></span><span>(</span><span><span class="hljs-variable">$ip</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$long</span></span><span>; </span><span><span class="hljs-comment">// 出力結果:3232235777</span></span><span>
</span></span>
上記の例では、 192.168.1.1が整数3232235777に変換されます。
IP2LONG()関数は、32ビットの符号なし整数を返します。 32ビット整数の表現範囲によれば、その値は0〜4294967295でなければなりません。これは、IP2long()変換の結果がゼロより大きい整数であることを意味します。 (たとえばIPv6で)より大きな値を処理するには、異なるメカニズムを使用する必要があります。
IP2long()から変換された整数は本質的に32ビット整数であり、そのような整数はPHPの数学操作に直接参加できます。 INTタイプのPHPは、ほとんどのシステムで署名された32ビット整数であるため、追加、減算、乗算、除算などの一般的な数学操作に使用できます。
たとえば、IPで構成された整数を追加または減算できます。
<span><span><span class="hljs-variable">$ip1</span></span><span> = </span><span><span class="hljs-string">'192.168.1.1'</span></span><span>;
</span><span><span class="hljs-variable">$ip2</span></span><span> = </span><span><span class="hljs-string">'192.168.1.2'</span></span><span>;
</span><span><span class="hljs-variable">$long1</span></span><span> = </span><span><span class="hljs-title function_ invoke__">ip2long</span></span><span>(</span><span><span class="hljs-variable">$ip1</span></span><span>);
</span><span><span class="hljs-variable">$long2</span></span><span> = </span><span><span class="hljs-title function_ invoke__">ip2long</span></span><span>(</span><span><span class="hljs-variable">$ip2</span></span><span>);
</span><span><span class="hljs-variable">$sum</span></span><span> = </span><span><span class="hljs-variable">$long1</span></span><span> + </span><span><span class="hljs-variable">$long2</span></span><span>;
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$sum</span></span><span>; </span><span><span class="hljs-comment">// 出力2 IP アドレスの翻訳された整数</span></span><span>
</span></span>
このタイプの操作は、結果がPHP整数タイプの表現範囲を超えない場合に有効です。一般的に言えば、計算結果は妥当な範囲内にあります。
ただし、非常に大きな数学操作を実行すると、PHP整数オーバーフローの問題に遭遇する可能性があります。 PHPは、通常32ビットまたは64ビットのさまざまなシステムのさまざまなサイズの整数を使用します。いくつかの32ビットシステムは、特に非常に多くの数を扱う場合、整数のオーバーフローを発生する可能性があります。
たとえば、加算または乗算の結果が32ビット整数( 4294967295 )の最大値を超えると、オーバーフローが発生し、計算結果が誤っています。したがって、 IP2LONG()によって変換された整数は数学的操作に直接参加できますが、大規模な操作を実行するときに、オーバーフローの問題に注意を払う必要があります。
PHPでは、整数の値がシステム整数の範囲を超える場合、PHPは自動的にフローティングポイント数に変換します。これにより、特に複雑な操作を実行する場合は、精度の損失につながる可能性があります。例えば:
<span><span><span class="hljs-variable">$ip1</span></span><span> = </span><span><span class="hljs-string">'255.255.255.255'</span></span><span>;
</span><span><span class="hljs-variable">$ip2</span></span><span> = </span><span><span class="hljs-string">'0.0.0.1'</span></span><span>;
</span><span><span class="hljs-variable">$long1</span></span><span> = </span><span><span class="hljs-title function_ invoke__">ip2long</span></span><span>(</span><span><span class="hljs-variable">$ip1</span></span><span>);
</span><span><span class="hljs-variable">$long2</span></span><span> = </span><span><span class="hljs-title function_ invoke__">ip2long</span></span><span>(</span><span><span class="hljs-variable">$ip2</span></span><span>);
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$long1</span></span><span> + </span><span><span class="hljs-variable">$long2</span></span><span>;
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$result</span></span><span>; </span><span><span class="hljs-comment">// 正確な問題に遭遇する可能性があります</span></span><span>
</span></span>
この例では、IPアドレスの整数値が大きすぎる場合、PHPはフローティングポイント数に変換されますが、浮動小数点数の精度制限により、最終計算結果がエラーになる場合があります。
整数のオーバーフローと精度の損失を回避するために、次の方法を採用できます。
64ビットの整数を使用します。環境が64ビットの整数をサポートしている場合、操作が整数範囲を超えないようにすることができます。 PHP_INT_SIZEを使用して、現在のPHP環境でサポートされている整数サイズを確認できます。
<span><span><span class="hljs-keyword">echo</span></span><span> PHP_INT_SIZE; </span><span><span class="hljs-comment">// 4 または 8,システムアーキテクチャに依存します</span></span><span>
</span></span>
GMPまたはBC MATH拡張機能を使用します:より大きな値に対して、PHPは、オーバーフローと精度の損失を回避し、任意の精度の整数と浮動小数点計算をサポートするGMPおよびBC Math拡張ライブラリを提供します。
たとえば、 gmp_add()を使用すると、高精度の追加を実行できます。
<span><span><span class="hljs-variable">$gmp1</span></span><span> = </span><span><span class="hljs-title function_ invoke__">gmp_init</span></span><span>(</span><span><span class="hljs-variable">$long1</span></span><span>);
</span><span><span class="hljs-variable">$gmp2</span></span><span> = </span><span><span class="hljs-title function_ invoke__">gmp_init</span></span><span>(</span><span><span class="hljs-variable">$long2</span></span><span>);
</span><span><span class="hljs-variable">$gmpSum</span></span><span> = </span><span><span class="hljs-title function_ invoke__">gmp_add</span></span><span>(</span><span><span class="hljs-variable">$gmp1</span></span><span>, </span><span><span class="hljs-variable">$gmp2</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-title function_ invoke__">gmp_strval</span></span><span>(</span><span><span class="hljs-variable">$gmpSum</span></span><span>);
</span></span>
IP2long()関数がIPアドレスを整数に変換すると、通常、数学操作に直接使用できます。ほとんどの場合、これらの整数はPHPの整数範囲を超えていないため、追加、減算、乗算、分割などの操作を実行できます。ただし、場合によっては、特に多数を実行する場合は、オーバーフローと精度の問題に注意を払う必要があります。これらの問題を回避するには、GMPやBC Math拡張機能など、64ビット整数またはPHPの高精度の数学的拡張を使用することを検討してください。
整数のPHPの処理メカニズムを理解し、拡張ライブラリを合理的に使用することにより、IPアドレス変換後に数学操作を実行するときに、データのオーバーフローまたは精度の損失によりエラー結果がないことを保証できます。