PHPでは、 array_diff()は、配列と戻りの違いを比較するための非常に実用的な機能です。値を比較して、最初の配列で要素を見つけるが、他の配列では発見されません。これは通常、文字列や整数の処理には問題ではありませんが、浮動小数点配列を扱う場合、浮動小数点数のために「予期しない」動作が発生する可能性があります。
簡単な例から始めましょう:
<?php
$a = [1.1, 2.2, 3.3];
$b = [2.2, 3.3];
$result = array_diff($a, $b);
print_r($result);
出力は次のとおりです。
Array
(
[0] => 1.1
)
この結果は期待に沿っています。ただし、場合によっては、浮動小数点数は、精度の制限により、 array_diff()と比較してエラーを引き起こす可能性があります。
浮動小数点数は、コンピューターの特定の小数を正確に表すことができず、わずかなエラーが発生する可能性があります。例えば:
<?php
$a = [0.1 + 0.2]; // 実際の値はです 0.30000000000000004
$b = [0.3];
$result = array_diff($a, $b);
print_r($result);
出力は次のとおりです。
Array
(
[0] => 0.30000000000000004
)
0.1 + 0.2 == 0.3と思われるかもしれませんが、コンピューター内のバイナリ浮動点表現により、この方程式は必ずしも真実ではありません。これは、array_diff()が2つの値が等しくないと考えると、誤判断を下すことを意味します。
Array_diff()の基礎となる層は、2つの値が等しいかどうかを判断するためのゆるい比較( == )に基づいています。しかし、浮動小数点数の精度の問題自体は、2つの数値が論理的に「等しい」場合でも、特に小数計算が含まれた後、メモリ内の表現が異なる可能性があることを意味します。
財務データ、センサーデータ、または正確な計算を必要とするその他のビジネスシナリオの処理では、 array_diff()のこの動作は以下につながる可能性があります。
データが存在するかどうかを誤って識別します
ビジネス判断ブランチの論理エラー
データの違いを正しく同期または比較できません
これはコードバグであるだけでなく、ビジネスセキュリティの問題である可能性があります。
PHPはarray_udiff()を提供します。これにより、開発者は独自の比較関数を提供できます。
<?php
function float_compare($a, $b) {
$epsilon = 0.00001; // 精度耐性
if (abs($a - $b) < $epsilon) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
$a = [0.1 + 0.2];
$b = [0.3];
$result = array_udiff($a, $b, 'float_compare');
print_r($result);
出力は次のとおりです。
Array
(
)
今回は、 array_udiff()は、2つが「等しい」ことを正しく識別し、浮動小数点エラーによって引き起こされる問題を回避します。
Array_udiff()またはカスタム関数を使用できない場合、「Curve Saves The Country」メソッドも浮動小数点番号をフォーマットします。
$a = array_map(function($v) {
return round($v, 5);
}, [0.1 + 0.2]);
$b = array_map(function($v) {
return round($v, 5);
}, [0.3]);
$result = array_diff($a, $b);
print_r($result);
この方法は、精度によって引き起こされるほとんどの問題を効果的に回避することもできますが、それでも注意して使用する必要があります。
Array_diff()を使用してフローティングポイントアレイを処理する場合、フローティングポイント数のPHP処理メカニズム、特に精度エラーの影響に特に注意する必要があります。浮動小数点数が直接比較されると、論理的なエラーやセキュリティリスクさえもつながる可能性があります。データの精度を確保するには、カスタマイズされた精度許容範囲の比較関数を使用してarray_udiff()を使用するか、データの統一フォーマットを実行することをお勧めします。
重要なデータを含む企業では、一見マイナーなエラーを無視すべきではありません。