Dans PHP, Array_Diff () est une fonction très pratique pour comparer les tableaux et les différences de retour. Il compare les valeurs pour découvrir des éléments dans le premier tableau mais pas dans d'autres tableaux. Ce n'est généralement pas un problème avec le traitement des chaînes et des entiers, mais lorsqu'il s'agit de tableaux à virgule flottante, un comportement "inattendu" peut se produire, en raison de nombres à virgule flottante.
Commençons par un exemple simple:
<?php
$a = [1.1, 2.2, 3.3];
$b = [2.2, 3.3];
$result = array_diff($a, $b);
print_r($result);
La sortie est:
Array
(
[0] => 1.1
)
Ce résultat est conforme aux attentes. Cependant, dans certains cas, les nombres de points flottants peuvent entraîner des erreurs par rapport à array_diff () en raison de limitations de précision.
Les nombres à virgule flottante ne peuvent pas représenter avec précision certaines décimales dans les ordinateurs, et il peut y avoir de légères erreurs. Par exemple:
<?php
$a = [0.1 + 0.2]; // La valeur réelle est 0.30000000000000004
$b = [0.3];
$result = array_diff($a, $b);
print_r($result);
La sortie est:
Array
(
[0] => 0.30000000000000004
)
Vous pourriez penser 0,1 + 0,2 == 0,3 , mais la représentation du point flottant binaire à l'intérieur de l'ordinateur rend cette équation non toujours vraie. Cela signifie que Array_Diff () tiendra compte des deux valeurs pas égales , ce qui entraînera une erreur de jugement.
La couche sous-jacente de Array_Diff () est basée sur une comparaison lâche ( == ) pour déterminer si les deux valeurs sont égales. Mais le problème de précision des nombres à virgule flottante lui-même signifie que même si deux nombres sont logiquement "égaux", leurs représentations en mémoire peuvent être différentes, surtout après que des calculs décimaux soient impliqués.
Dans le traitement des données financières, des données de capteurs ou d'autres scénarios commerciaux qui nécessitent des calculs précis, ce comportement de Array_Diff () peut conduire à:
Identifier à tort si les données existent
Erreurs logiques dans la branche judiciaire commerciale
Impossible de synchroniser ou de comparer correctement les différences de données
Il s'agit non seulement d'un bogue de code, mais peut même être un problème de sécurité commerciale .
PHP fournit Array_udiff () , qui permet aux développeurs de fournir leurs propres fonctions de comparaison, qui peuvent implémenter une logique de différence de point flottante plus sûre:
<?php
function float_compare($a, $b) {
$epsilon = 0.00001; // Tolérance à la précision
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);
La sortie est:
Array
(
)
Cette fois, array_udiff () identifie correctement que les deux sont "égaux", évitant les problèmes causés par l'erreur de point flottante.
Lorsque vous ne pouvez pas utiliser array_udiff () ou des fonctions personnalisées, il existe également une méthode "Curve enregistre le pays" pour formater les numéros de point flottants:
$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);
Cette méthode peut également éviter efficacement la plupart des problèmes causés par la précision, mais il doit encore être utilisé avec prudence.
Lorsque vous utilisez Array_Diff () pour traiter les tableaux de points flottants, une attention particulière doit être accordée au mécanisme de traitement PHP sur les nombres de points flottants, en particulier l'impact des erreurs de précision. Si les nombres à virgule flottante sont directement comparés, cela peut entraîner des erreurs logiques et même des risques de sécurité. Pour garantir la précision des données, il est recommandé d'utiliser Array_udiff () avec une fonction de comparaison de tolérance de précision personnalisée, ou d'effectuer un formatage unifié des données.
Dans les entreprises impliquant des données importantes, toute erreur apparemment mineure ne doit pas être ignorée.