Nombre de valeur maximum dans un tableau PHP

Résolu
Bonjour,

Dans mon programme PHP, je dois calculer toute les possibilités des calculs possible. Par contre, lorsque je lance mon script, il m'indique que j'ai atteint la capacité maximale du tableau, alors qu'est-ce que je dois faire pour enlever cette erreur et que les changements effectuer n'est aucun impact sur le reste de mon script?

Voici mon code :

<?php

//Fonctions
function getClosest($search, $arr) {
   $closest = null;
   foreach ($arr as $item) {
      if ($closest === null || abs($search - $closest) > abs($item - $search)) {
         $closest = $item;
      }
   }
   return $closest;
}

//Début des tableaux utilisés pour calculer toute les possibilités de ratio possible
$gear1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 , 13, 14, 15, 16, 17, 18, 19 ,20, 21, 22, 23, 24, 25, 26, 27, 28 ,29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125];
$gear2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 , 13, 14, 15, 16, 17, 18, 19 ,20, 21, 22, 23, 24, 25, 26, 27, 28 ,29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125];
$gear3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 , 13, 14, 15, 16, 17, 18, 19 ,20, 21, 22, 23, 24, 25, 26, 27, 28 ,29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125];
$gear4 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 , 13, 14, 15, 16, 17, 18, 19 ,20, 21, 22, 23, 24, 25, 26, 27, 28 ,29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125];
	
$recherche = 0.44444444444445;

$resultats = array();
$debug = array();
foreach($gear4 as $k4=>$v4){
	foreach($gear3 as $k3=>$v3){
		foreach($gear2 as $k2=>$v2){
			foreach($gear1 as $k1=>$v1){
				$calc = ($v1/$v2)*($v3/$v4);
				$resultats [] = $calc;
				$debug[] = array('calc'=>$calc,'valeurs'=>array($v1,$v2,$v3,$v4));
				
			}
		}
	}
}	
sort($resultats);

$valPlusProche = getClosest($recherche,$resultats);
echo "<br> Valeur cherchée : " . $recherche;
echo "<br>Plus proche résultat : "  . $valPlusProche;

echo"<pre>";
print_r($debug);
echo"</pre>";
?>

3 réponses

Résumé de la discussion

Le problème central est l'explosion des données à traiter lors du calcul de toutes les possibilités et l'atteinte de la capacité maximale du tableau, provoquant une erreur mémoire et un ralentissement. Une réponse propose d'éviter la force brute en simplifiant l'expression en calc = v5/v6 et en générant tableau des produits v1×v2, réutilisable pour v3×v4, puis d'utiliser une recherche dichotomique pour approcher v6 autour de v5. On peut aussi stocker les résultats et retrouver facilement les valeurs v1, v2, v3 et v4 à partir des meilleurs ratios, ce qui facilite l'identification des combinaisons utilisées et accélère les recalculs. Par ailleurs, le fil rappelle que l'optimisation peut nécessiter de limiter le bruit et d'évaluer le coût mémoire d'un pré-calcul.

Bobot (l’IA à votre service)
  1. En fait ton problème est très mathématique.
    Ton approche par force brute va fonctionner, mais en des temps très longs ou en consommant beaucoup de mémoire.
    Il faut trouver des astuces pour réduire ce temps.
    Ce que tu veux, c'est trouver les facteurs v1, v2, v3 et v4 qui permettent le mieux d'approcher un résultat donné par la formule $calc = ($v1/$v2)*($v3/$v4);
    Ce que je ferais à ta place, c'est déjà simplifier cette écriture en $calc = $v5/$v6;
    Tu peux créer un tableau des V qui contient tous les produits de deux nombres v1 et v2. L'avantage c'est que le même tableau peut être utilisé pour v5 et v6.
    Pourquoi ? Parce qu'ainsi, on peut contrôler la croissance ou décroissance du résultat au fur et à mesure que les valeurs sont testées. On peut même trouver tout de suite le v6 qui approche le mieux v5 : v6 = v5 / recherche : tu le calcules et trouves les v6 qui encadrent au mieux cette valeur dans le tableau des V (un plus grand et un plus petit que le v6 trouvé, qui ne sera pas forcément entier. Comme le tableau est trié, tu peux aller assez vite sans le parcourir complètement, par exemple par dichotomie). Tu gardes ensuite le meilleur des deux. Et ainsi de suite pour chaque v5.

    Une fois que tu as les v5 et v6, tu peux retrouver les v1, v2, v3 et v4 qui correspondent (encore plus facilement si tu les as stockés en mémoire également au début)

    Bon c'est peut-être un peu confus à écrire comme ça, mais cette approche pourra t'éviter de très nombreux calculs : je t'invite à y réfléchir sérieusement.
    1
    1. Modérateur
      Cela fait quand même 244'140'625 possibilités ...
      Compte tenu de la taille de chaque entrée dans ton tableau Debug, tu dois un peu exploser la RAM ...

      Si tu as besoin juste de la valeur la plus proche, fais-le directement et non après avoir tout calculer.
      0
      1. Bonjour,

        Pourrais-tu me diriger un peu?
        0
      2. Contributeur
        @Anonyme1234_7288bonjour,
        décris, avec des mots, ce que fait ton programme.
        cela t'aidera à comprendre comment l'optimiser.
        0
      3. @yg_beBonjour,

        Je sais comment fonctionne mon programme, c'est seulement que je cherche une solution pour pouvoir mettre dans les tableaux $gear1, $gear2, $gear3 et $gear4, des nombres jusqu'à 125 et qu'il n'y est aucune erreur qui s'affiche.

        Pourriez-vous m'aider?
        0
      4. Contributeur
        @Anonyme1234_7288en fait, ton programme est extrêmement mal conçu, et j'essaie que tu en prennes conscience, de façon à ce que, la prochaine fois, tu ne fasses plus cette erreur de conception.
        je t'invite donc à réfléchir et à découvrir cette erreur.
        je suggère que tu écrives, avec des mots, ce que fait ton programme.

        une autre façon de faire serait peut-être de partir d'une situation similaire, réelle ou imaginée, sans utilisation d'ordinateur. cela pourrait t'aider à te découvrir comment optimiser.
        0
      5. @yg_beMerci d'essayer de me faire prendre conscience, mais ça fait environ deux mois que je travail sur ce programme et je n'arrive pas à trouver ce qu'il ne va pas.
        0
    2. Bonjour,

      Ce qu'essaie de te dire yg_be, c'est que ton programme ne pourra pas fonctionner comme ça.
      Ce n'est pas une question de changer un ou deux trucs pour que « ça marche ». Le problème, c'est juste que tu essaies de stocker en mémoire des centaines de millions de valeurs. C'est énorme, c'est trop pour php.

      Donc yg_be essaie de comprendre ce que tu veux que ton programme fasse, pour trouver une autre façon de le faire sans avoir à stocker tout ça.

      Par exemple, pourquoi vouloir stocker tous les ratios résultant des combinaisons de ces quatre valeurs ? Pourquoi ne pas simplement recalculer un ratio quand il est utile ?

      Xavier
      0
      1. Bonjour,

        D'accord je comprend. Alors mon programme fonctionne de sorte que je calcul tous les ratios de chaque possibilité et je les stock dans un tableau. Par la suite, je trouve le nombre parmi les ratios le plus proches du nombre de la variable $recherche. Par la suite, je recherche dans ma liste des ratios que j'ai trouver précédemment et j'affiche les nombre qui ont été utilisé pour calculer le ratio qui correspond au nombre le plus proche.

        Il ce peut que mon explication ne soit pas claire mais je vais joindre mon code de nouveau et inclure quelque commentaire.

        Voici mon code :

        <?php
        //Début fonctions pour nombre le plus proche
        function getClosest($search, $arr) {
           $closest = null;
           foreach ($arr as $item) {
              if ($closest === null || abs($search - $closest) > abs($item - $search)) {
                 $closest = $item;
              }
           }
           return $closest;
        }
        //Fin fonctions pour nombre le plus proche
        
        //Début des tableaux utilisés pour calculer toute les possibilités de ratio possible
        $gear1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,/* 17, 18, 19, 20*/];
        $gear2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,/* 17, 18, 19, 20*/];
        $gear3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,/* 17, 18, 19, 20*/];
        $gear4 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,/* 17, 18, 19, 20*/];
        //Fin des tableaux utilisés pour calculer toute les possibilités de ratio possible
        
        //Début de la variable stockant le nombre recherché
        $recherche = 4.8888888888889;
        //Fin de la variable stockant le nombre recherché
        
        
        //Début du calcul des ratios
        $resultats = array();
        $debug = array();
        foreach($gear4 as $k4=>$v4){
        	foreach($gear3 as $k3=>$v3){
        		foreach($gear2 as $k2=>$v2){
        			foreach($gear1 as $k1=>$v1){
        				$calc = ($v1/$v2)*($v3/$v4);
                    $resultats [] = $calc;
        				$debug[] = array('calc'=>$calc,'valeurs'=>array($v1,$v2,$v3,$v4));
        				
        			}
        		}
        	}
        }	
        //Fin du calcul des ratios
        
        //Début affichage du nombre rechercher et du nombre le plus proche du nombre rechercher
        sort($resultats);
        $valPlusProche = getClosest($recherche,$resultats);
        echo "<br> Valeur cherchée : " . $recherche;
        echo "<br>Plus proche résultat : "  . $valPlusProche;
        //Fin affichage du nombre rechercher et du nombre le plus proche du nombre rechercher
        
        echo"<pre>";
        //Début affichage du tableau
        print_r($debug);
        echo"</pre>";
        //Fin affichage du tableau
        
        0
      2. Contributeur
        @Anonyme1234_7288c'est hyper clair:
        mon programme fonctionne de sorte que je calcul tous les ratios de chaque possibilité et je les stock dans un tableau. Par la suite, je trouve le nombre parmi les ratios le plus proches du nombre de la variable $recherche. Par la suite, je recherche dans ma liste des ratios que j'ai trouver précédemment et j'affiche les nombre qui ont été utilisé pour calculer le ratio qui correspond au nombre le plus proche.

        essayons une analogie:
        - tu as un atlas avec une page par pays, chaque page étant une carte du pays avec toutes les villes de ce pays, et leur nombres d'habitants.
        - tu dois déterminer quelle ville a le nombre d'habitants le plus proche d'un nombre donné.
        - tu as un crayon et une grande feuille, aussi grande que tu le souhaites
        Comment fais-tu ce travail?
        0
      3. @yg_beJe note sur la feuille grâce à mon crayon chaque nombre qui semble le plus proche du nombre d'habitant.
        0
      4. Contributeur
        @Anonyme1234_7288c'est un peu flou comme réponse, ce serait mieux d'être plus précis: décris les instructions que tu donnerais à quelqu'un pour faire exactement ce que tu veux qu'il fasse.

        si tu appliquais la même logique que ton programme, que noterais-tu sur la feuille?
        0
      5. @yg_beJe noterais le nom du pays et le nombre d'habitant pour chaque. Je ferais ceci pour chacun et par la suite je les comparerais au nombre recherché. Finalement, je retiens le nombre d'habitant le plus proche du nombre recherché.
        0