8768 sujets

Développement web côté serveur, CMS

Bonjour,

Bête question peut-être, mais sait-on jamais, on a parfois des surprises...
Existe-t-il selon vous une fonction PHP native qui permette de valider un résultat à X unités près?

Par exemple, si mon résultat vaut 28 et que j'attends 37, et que je tolère toute réponse à 10 unités près, la fonction retournerait TRUE. Si mon résultat était 26, il retournerait FALSE.

Il y a une fonction PHP qui fait ça, selon vous?

Merci pour vos réponses,

Reka
Oui, c'est une fonction facile à mettre en place quand il s'agit de deux éléments, mais qui me donne du fil à retordre pour 3.

Sur base d'un tableau de 3 éléments, il faut donc que je voie si un écart de 5 (n) sépare ou non mes nombres.

Exemple : [a, b, c] = [43, 39, 50]

a et b sont différents de 4 (ok) mais a et c de 7 (ko), il convient donc d'obtenir un FALSE.

Quel serait le chemin le plus direct pour créer cette fonction?

- tri du tableau => donne un tableau2 réorganisé numériquement (ici : [d, e, f] = [b, a, c])
- élément intermédiaire (pas le plus petit ni le plus grand, càd "e") - n et + n :


if (e-n < d) && (e+n > f) {
return TRUE;
} else {
return FALSE;
}


C'est bon, ou il y a moyen d'optimiser?

Merci Smiley smile
Modifié par Reka (15 Mar 2016 - 09:20)
Bonjour,
Certainement qu'il y a plus joli, mais je propose ceci. la première valeur est comparée avec toutes les suivantes, puis la seconde avec ses suivantes etc ... Je pense que c'est ce que tu souhaites faire, mais j'ai un doute car tu parles de trier ton tableau.

<?php
$arr = array(43,39,50,12,89,73,11,145);
$limit = 5;

foreach ($arr as $ka => $a) {
    if( $ka == count($arr)-1 ){
        continue;
    }
    echo "<ul><li><strong>compare cle $ka</strong> avec:</li>";
    for( $i = $ka+1; $i < count($arr); $i++ ){
        $testdiff = abs($a - $arr[$i]) < $limit ? "Ok" : "KO";
        echo "<li>cle $i => $testdiff</li>";
    }
    echo "</ul>";
}

Modifié par loicbcn (15 Mar 2016 - 10:49)
Bonjour,

Perso, je propose autre chose :
function test_limites($tableau, $limite) {
  $etendue = max($tableau)-min($tableau);
  return $etendue<=$limite ? "true" : "false";
}

Et ça devrait fonctionner avec un tableau de n valeurs...
Modifié par SolidSnake (15 Mar 2016 - 13:54)
Administrateur
Bonjour,

Reka a écrit :
Oui, c'est une fonction facile à mettre en place quand il s'agit de deux éléments, mais qui me donne du fil à retordre pour 3.
(…)
C'est bon, ou il y a moyen d'optimiser?

Merci Smiley smile

c'est un peu différent du sujet de départ (il y a une valeur cible dont il ne faut pas s'écarter de plus de "delta"). Est-ce que le nombre de valeurs va être grand ou toujours de 3 ?

Si le tableau a beaucoup de valeurs, mieux vaut le trier : c'est un algorithme rapide (bien plus que 2 boucles imbriquées qui est d'une complexité en O(N^2) càd que 2 fois plus de valeurs prend 4 fois plus de temps à traiter. 3x => 9x etc Ouch EDIT : N*(N-1)/2 très exactement ; je sais plus si c'est O(N^2) ou moins m'enfin l'ordre de grandeur est là Smiley confused ) et la 2e étape consiste à re-parcourir le tableau ordonné à la recherche d'un écart plus grand que ton delta, ça c'est rapide (en O(N) càd que ça prend le double du temps pour le double de valeurs).

Dans ton dernier exemple, je n'ai pas compris d'où sortaient d, e et f ? Enfin à quoi correspond tableau2 par rapport à tableau ?
Modifié par Felipe (15 Mar 2016 - 14:57)
Là ça devient carrément vicieux Smiley biggrin . Est-ce que tous les nombres du tableau doivent tenir dans un écart correspondant à une certaine valeur ou c'est valable uniquement pour le nombre qui vient après ? Exemple si j'ai bien compris, pour un écart de 5, on peut donc avoir [1, 5, 3, 0] mais pas [1, 4, 8, 13] (?)
J'aurais pensé aussi à une imbrication de boucles du style :

function check($array, $delta) {

	$r = true;
	$l = count($array);
	
	for($i = 0; $i < $l; $i++) {
		for($j = 0; $j < $l; $j++) {
			if (abs($array[$i] - $array[$j]) > $delta) {
				$r = false;
				break 2;
			}
		}
	}

	return $r;

}

check(array(43, 40, 50), 5); // FALSE
check(array(43, 40, 50), 7); // TRUE
Houla houla, je n'avais pas pris garde aux réponses en masse. Merci pour vos idées et propositions.

Felipe a écrit :
Est-ce que le nombre de valeurs va être grand ou toujours de 3 ?

le tableau se limite toujours à 3 valeurs, oui.
(on est dans de la 3D, en quelques sortes : j'ai un point hauteur, un point largeur, un point profondeur)

Felipe a écrit :

Dans ton dernier exemple, je n'ai pas compris d'où sortaient d, e et f ? Enfin à quoi correspond tableau2 par rapport à tableau ?


si tableau = [a,b,c], tableau2 est une copie de tableau avec les éléments a,b,c triés que j'ai rebaptisés d,e,f pour éviter la confusion entre valeurs bordéliques et valeurs classées, simplement...

Copie nécessaire parce que je ne pouvais pas me permettre de perdre les valeurs [a,b,c] telles que sorties originellement, vu qu'elles correspondent à un point donné dans un espace 3D.

Je vais étudier vos propositions et retenir ce qui est le plus direct et adapté. Merci encore !
Administrateur
Oki, dans ce cas tu peux calculer les 3 deltas d1=abs(b-a), d2=abs(c-a) et d3=abs(c-b) puis jeter le max de ces 3 valeurs (*) : il te reste les deltas entre la valeur du milieu et les 2 extrêmes (et tu viens de jeter le delta entre la valeur min et la valeur max qui ne t'intéresse pas)

Si le 1er delta restant est inférieur (ou égal) à ta limite et le 2e aussi alors OK sinon #fail

Cas limites : si 2 valeurs sont identiques, il va y avoir un delta nul et les 2 autres égaux. Soit il faut garder un des 2 deltas (n'en jeter qu'un), soit si l'un est nul alors il suffit de comparer n'importe lequel des 2 autres à ta limite.
3 valeurs identiques => deltas nuls

(*) max(a, max(b,c)) donne le max des 3.
Je vois pas mieux que d'enchaîner les if et else if (?)
Si d1 est le max alors r1 = d2 et r2 = d3
sinon si d2 est le max alors r1 = d1 et r2 = d3
sinon (si d3 est le max mais on s'en doute !) alors r1 = d1 et r2 = d2

Et tu peux alors comparer r1 et r2 à ta limite.

edit : Mais avant ça tu peux déjà tester les cas limites.
Si le max des deltas est nul, alors ils sont tous nuls et c'est OK (edit2 : le test ci-dessus renvoie un truc correct càd r1=0 et r2 = 0 dans ce cas ==> pas de test particulie rà ajouter)
Si 2 valeurs sont identiques, alors 2 deltas parmi d1, d2 et d3 sont identiques et les if else if ci-dessus sélectionnent bien 2 des 3 deltas (si d1 est un des max, on cherche pas à savoir si c'est aussi le cas d'un autre mais on assigne r1 et r2 et fin des tests)
Modifié par Felipe (15 Mar 2016 - 22:30)
Merci Felipe ! Et merci à tous les autres !
J'adapte mon code sur base de vos utiles remarques Smiley cligne Smiley smile

Bonne soirée.
Bonjour,

Ça m'intéresse de voir la solution retenue, pour être sûre d'avoir bien compris la problématique.

Un curieux mal de tête s'est installé avant la fin de la dernière réponse de Felipe Smiley biggol