Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Page 86 sur 334 PremièrePremière ... 3676787980818283848586878889909192939496136186 ... DernièreDernière
Affichage des résultats 2 551 à 2 580 sur 10008
  1. #2551
    Ouep, enculage de mouches, toussatoussa.

  2. #2552
    Citation Envoyé par rOut Voir le message
    Bah ouais mais de toute manière c'est quoi l'autre solution sans exceptions ? Je veux dire, soit tu checkes que chaque valeur est OK, soit pas mais dans tous les cas ton check va difficilement se vectoriser non ?
    Si tu veux être sûr que les valeurs sont toutes valides, tu vas devoir faire le check pour chaque valeur.
    J'avais commencé à me lancer dans des explications compliquées avec plein de code assembleur, mais je me suis embrouillé tout seul. La vectorisation statique de code séquentiel, de toute façon ça marche pas, la preuve j'y arrive pas.

    Donc je vais plutôt prendre un exemple que je connais mieux. Suppose que tu dois compiler les codes pseudo-OpenCL suivants pour Xeon Phi. (Si tu n'aimes pas OpenCL, tu peux réécrire ça en CUDA, en GLSL ou en ISPC).
    Tu as droit à tout le jeu d'instructions de Knights Corner, en particulier les instructions SIMD prédiquées par des registres de masque et les comparaisons SIMD qui écrivent dans lesdits registres.
    Code:
    device bool saxpy_var(float * x, float a, float const * y, int n)
    {
    	size_t tid = get_local_id(0);
    	size_t tcnt = get_local_size(0);
    	bool error = false;
    	for(int i = tid; i < n && !error; i += tcnt)
    	{
    		x[i] = a * x[i] + y[i];
    		if(isnan(x[i]) {
    			error = true;
    		}
    	}
    	return error;
    }
    
    device bool saxpy_ret(float * x, float a, float const * y, int n)
    {
    	size_t tid = get_local_id(0);
    	size_t tcnt = get_local_size(0);
    	for(int i = tid; i < n; i += tcnt)
    	{
    		x[i] = a * x[i] + y[i];
    		if(isnan(x[i]) {
    			return true;
    		}
    	}
    	return false;
    }
    
    global main_kernel_ret(float * x, float a, float const * y, int n)
    {
    	if(saxpy_ret(x, a, y, n))
    		printf("Große Malheur!");
    }
    
    device void saxpy_except(float * x, float a, float const * y, int n)
    {
    	size_t tid = get_local_id(0);
    	size_t tcnt = get_local_size(0);
    	for(int i = tid; i < n; i += tcnt)
    	{
    		x[i] = a * x[i] + y[i];
    		if(isnan(x[i]) {
    			throw 42;
    		}
    	}
    }
    
    global main_kernel_except(float * x, float a, float const * y, int n)
    {
    	try {
    		saxpy_except(x, a, y, n))
    	}
    	catch(...) {
    		printf("Große Malheur!");
    	}
    }
    Indice : ils sont classés par ordre de difficulté.

  3. #2553
    Dans mon projet de DF-like, j'ai commencé par faire des calculs de matrice pas optimisés du tout, avec deux boucles for et tout le bordel.
    Puis j'ai remplacé tout ça par de l'assembleur inline écrit à la main et qui utilise le SIMD.

    Je ne me souviens plus exactement du résultat, mais ça allait quelque chose comme dix fois plus vite.
    Donc enculage de mouche... ou pas.
    Rust fanboy

  4. #2554
    Citation Envoyé par Møgluglu Voir le message
    J'avais commencé à me lancer dans des explications compliquées avec plein de code assembleur, mais je me suis embrouillé tout seul. La vectorisation statique de code séquentiel, de toute façon ça marche pas, la preuve j'y arrive pas.

    Donc je vais plutôt prendre un exemple que je connais mieux. Suppose que tu dois compiler les codes pseudo-OpenCL suivants pour Xeon Phi. (Si tu n'aimes pas OpenCL, tu peux réécrire ça en CUDA, en GLSL ou en ISPC).
    Tu as droit à tout le jeu d'instructions de Knights Corner, en particulier les instructions SIMD prédiquées par des registres de masque et les comparaisons SIMD qui écrivent dans lesdits registres.
    Indice : ils sont classés par ordre de difficulté.
    Je suis censé faire quelque chose avec ça ?

    Non parce que je ne saurais pas vraiment quoi dire à ce sujet. Simplement que pour moi je dirais que ce n'est pas la manière dont l'erreur est retournée qui ferait merdoyer la vectorisation mais le check "isnan(x[i])". Parce que tu checkes les valeurs une par une, et que ça doit pas bien se vectoriser sur 4 floats d'un coup.

    Dans les trois cas, la découverte d'une isnan entraîne aussi l'arrêt de l'itération. Hors tu n'as aucun moyen de savoir sur quelle valeur tu étais censé t'arrêter avant d'avoir fait la multiplication, ça peut très bien être au milieu d'un pack de floats que tu viens juste de multiplier d'un coup. Et je suppose aussi que t'es censé retourner un résultat à peu près exact, c'est à dire que si tu trouves un isnan dans le premier résultat d'un groupe de 4 floats vectorisés, t'es pas censé avoir multiplié les trois autres... parce que t'es allé trop vite, ni le reste des valeurs si tu t'amuses à le faire dans le désordre.

    Qu'est ce que le compilateur est censé faire du coup ? Vectoriser sur le plus grand nombre d'éléments possibles, puis vérifier chaque résultat et si tu t'aperçois que t'en a trop fait, recommencer le calcul sur juste ce qu'il fallait et retourner le résultat ? Dans ce cas, en quoi est-ce différent quelque soit la manière dont l'erreur est retournée ?

    ---------- Post added at 22h06 ---------- Previous post was at 21h58 ----------

    Citation Envoyé par Froyok Voir le message
    Cette dernière page...

    http://www.froyok.fr/archives/uplo/0...3811-IwQNW.gif

    (Vous êtes des fous)
    Le topic des bébés c'est .
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  5. #2555
    Citation Envoyé par Foudge Voir le message
    Si c'est bien ce sont parle Tomaka17, alors en C# tu peux par exemple utiliser Dictionary.
    Mais à vrai dire je ne suis pas bien sûr d'avoir compris ton besoin ni ton problème

    edit: en fait t'as déjà un tableau de correspondance avec tous les cas gérés du type x + y + ... = R, et ce que tu cherches est un moyen simple et rapide de trouver la partie droite de l'égalité en fonction de la partie gauche, sans devoir de taper plein de if ou de switch ?
    Je veux refaire le même système de craft que dans un minecraft ou project zomboid. Tu glisses tes objets dans une zone qui se charge de les additionner et te retourner un autre objet comme résultat.

  6. #2556
    Citation Envoyé par Tomaka17 Voir le message
    D'ailleurs pour moi t'es même pas censé utiliser les exceptions en cas d'erreur de la part de l'utilisateur.
    ...
    Le try-catch est là "au cas où", mais ne devrait se déclencher qu'en cas d'erreur bizarre, du genre erreur d'écriture dans le fichier ou incohérence dans les données qui étaient pourtant cohérentes au moment de l'ouverture.
    Le fait que l'utilisateur essaye de faire quelque chose qu'il n'a pas le droit de faire ou rentre un input invalide n'est pour moi pas dans le cadre des exceptions.
    Approved.

  7. #2557
    Citation Envoyé par rOut Voir le message
    Non parce que je ne saurais pas vraiment quoi dire à ce sujet. Simplement que pour moi je dirais que ce n'est pas la manière dont l'erreur est retournée qui ferait merdoyer la vectorisation mais le check "isnan(x[i])". Parce que tu checkes les valeurs une par une, et que ça doit pas bien se vectoriser sur 4 floats d'un coup.
    Pourquoi pas ? Tu checkes toutes les valeurs en même temps, tu récupères un vecteur de booléens, que tu peux utiliser comme masque pour prédiquer l'exécution des instructions suivantes. Tu peux aussi tester si tous les bits du masque sont à 0 ou tous à 1.

    Dans les trois cas, la découverte d'une isnan entraîne aussi l'arrêt de l'itération. Hors tu n'as aucun moyen de savoir sur quelle valeur tu étais censé t'arrêter avant d'avoir fait la multiplication, ça peut très bien être au milieu d'un pack de floats que tu viens juste de multiplier d'un coup. Et je suppose aussi que t'es censé retourner un résultat à peu près exact, c'est à dire que si tu trouves un isnan dans le premier résultat d'un groupe de 4 floats vectorisés, t'es pas censé avoir multiplié les trois autres... parce que t'es allé trop vite, ni le reste des valeurs si tu t'amuses à le faire dans le désordre.
    C'est exactement pour ça que j'ai pris un exemple en OpenCL. Sinon c'est vite prise de tête. Ici, tu t'en fous de l'ordre, tu vectorises entre des threads différents, et l'ordre d'exécution entre les threads n'est pas spécifié.

    Qu'est ce que le compilateur est censé faire du coup ? Vectoriser sur le plus grand nombre d'éléments possibles, puis vérifier chaque résultat et si tu t'aperçois que t'en a trop fait, recommencer le calcul sur juste ce qu'il fallait et retourner le résultat ? Dans ce cas, en quoi est-ce différent quelque soit la manière dont l'erreur est retournée ?
    Non, pas besoin de trucs compliqués comme retourner en arrière. C'est juste un exercice pour la gestion de flot de contrôle en SIMD.

    Pour le saxpy sans le check, ça donne par exemple :
    Code:
    vmov I, Tid          ; I[j] = Tid[j] forall j
    mov k, 0xffff        ; k[j] = 1 forall j
    beginfor:
    (k) vcmp.lt k, I, n  ; k[j] = (I[j] < n) when k[j]
    jmp.none k, endfor   ; if(k[j]=0 forall j)...
    (k) vgather Xt, x[I] ; xt[j] = x[I[j]] when k[j]
    (k) vgather Yt, y[I]
    (k) vfma Xt, Xt, A, Yt
    (k) vscatter x[i], Xt
    (k) vadd I, I, Tnum
    jmp beginfor
    endfor:
    ret
    Toutes les variables sont des vecteurs. k est un vecteur de booléens, ce qui revient à un int16. Les masques de prédication sont entre parenthèses.
    Le code n'est pas optimisé du tout. Le compilo est un peu con, il n'a pas vu qu'on accédait à des éléments adjacents donc il émet des gather/scatter là où des load/store de vecteurs suffiraient.

  8. #2558
    Pour le saxpy sans le check, ça donne par exemple :
    Après ça j'ai décroché.

    Sinon, ton histoire de vecteur de booléen, je ne vois pas bien comment, c'est le résultat des multiplications que tu vérifies, donc tu vas te taper toutes les opérations et vérifier ensuite.
    Et je persiste sur l'histoire du check. Si ta condition te sert à arrêter l'itération, comme c'est le cas ici, tu n'as pas le droit de multiplier plus de valeurs que ce qui est écrit, sinon c'est que la logique compilée n'est pas la même que la logique du programme.
    Si tu t'en branles, c'est que ton check n'est pas important, et autant ne pas le faire, ou le faire après (ou avant, comme je le faisais dans des boucles supplémentaires).

    Sinon, pour rigoler un coup, j'ai fait un truc totalement horrible... Tellement que je le met en spoiler tiens.
    Faut pas faire ça chez vous les enfants, mais c'est assez mortel et tu ne pourras pas venir me dire que mon exception viens perturber la vectorisation de la boucle :
    Code:
    Spoiler Alert!
    #include <cstdio> #include <cmath> #include <cfloat> #include <iostream> #include <exception> #include <stdexcept> #include <signal.h> void sigfpe_handler(int sig) { throw std::runtime_error("hop hop hop on s'arrete la monsieur."); } void saxpy_c(float* __restrict__ x, float a, float* __restrict__ y, int n) { for (int i = 0; i != n; i += (1 / (x[i] == x[i]))) { x[i] = a * x[i] + y[i]; } } int main(int argc, char const* argv[]) { signal(SIGFPE, &sigfpe_handler); float x[] = { FLT_MAX* FLT_MAX }; float y[] = { 0.0 }; float a = 0; float n = sizeof(x) / sizeof(float); try { saxpy_c(x, a, y, n); } catch (std::exception const& e) { std::cout << "haha, dans ton cul le signal: " << e.what() << std::endl; } return static_cast< int >(x[0]); }
    Testé et certifié avec gcc -O3 -fnon-call-exceptions

    Edit: En fait c'est -fnon-call-exceptions qu'il lui faut pour être content avec ce code (plus besoin de wrapper ou de désactiver les inline).
    Dernière modification par rOut ; 23/11/2012 à 00h40.
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  9. #2559
    Citation Envoyé par rOut Voir le message
    Après ça j'ai décroché.
    On ne vectorise pas la boucle for. On forme des vecteurs entre différents work-items OpenCL (j'ai qualifié de global la fonction principale, je voulais dire kernel, c'est l'effet CUDA). Comme le ferait un GPU, ou une vraie archi SIMD en forme d'armoire avec des leds qui clignotent (Connection Machine, Maspar, etc.). On peut vectoriser de cette façon même s'il n'y a pas de boucle du tout. Tu peux prendre un shader comme exemple.
    Ici, seuls les work-items qui ont rencontré une erreur doivent s'arrêter tout de suite, les autres doivent continuer jusqu'à la fin comme si de rien n'était.

    Sinon, pour rigoler un coup, j'ai fait un truc totalement horrible... Tellement que je le met en spoiler tiens.
    Faut pas faire ça chez vous les enfants, mais c'est assez mortel et tu ne pourras pas venir me dire que mon exception viens perturber la vectorisation de la boucle :
    C'est même pas vraiment horrible. Tu peux même faire plus simple :
    Code:
    #include <cstdio>
    #include <cmath>
    #include <cfloat>
    #include <iostream>
    #include <exception>
    #include <stdexcept>
    
    #include <signal.h>
    #include <fenv.h>
    
    void sigfpe_handler(int sig) {
      throw std::runtime_error("hop hop hop on s'arrete la monsieur.");
    }
    
    void saxpy_c(float* __restrict__ x, float a, float* __restrict__ y, int n) {
      for (int i = 0; i != n; i++) {
        x[i] = a * x[i] + y[i];
      }
    }
    
    int main(int argc, char const* argv[]) {
      signal(SIGFPE, &sigfpe_handler);
      feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
    
      float x[] = { FLT_MAX* FLT_MAX };
      float y[] = { 0.0 };
      float a   = 0;
      float n   = sizeof(x) / sizeof(float);
    
      try {
        saxpy_c(x, a, y, n);
      } catch (std::exception const& e) {
        std::cout << "haha, dans ton cul le signal: " << e.what() << std::endl;
      }
    
      return static_cast< int >(x[0]);
    }
    Mais ça ne tournera pas sous Xeon Phi. Il ne gère pas les exceptions FP.
    Et si tu compiles en x87, il faut rajouter une instruction nop flottante à la fin, parce que les exceptions sont envoyées lors de l'exécution de l'instruction flottante suivante (une histoire de câblage de copro externe dans les années 80).

  10. #2560
    Tu peux passer par un système de "clef" également :
    Viande = 1
    Feu = 2
    Viande + Feu = 3

  11. #2561
    Viande = 1
    Feu = 2
    Viande cuite = 3
    Barre de fer = 4
    Charbon = 5
    Epée = 9

    Donc :
    Viande cuite + viande cuite + viande cuite = Epée
    Viande cuite + viande = Barre de fer
    Viande x5 = charbon
    Rust fanboy

  12. #2562
    Citation Envoyé par Møgluglu Voir le message
    On ne vectorise pas la boucle for. On forme des vecteurs entre différents work-items OpenCL (j'ai qualifié de global la fonction principale, je voulais dire kernel, c'est l'effet CUDA). Comme le ferait un GPU, ou une vraie archi SIMD en forme d'armoire avec des leds qui clignotent (Connection Machine, Maspar, etc.). On peut vectoriser de cette façon même s'il n'y a pas de boucle du tout. Tu peux prendre un shader comme exemple.
    Ici, seuls les work-items qui ont rencontré une erreur doivent s'arrêter tout de suite, les autres doivent continuer jusqu'à la fin comme si de rien n'était.

    Mais ça ne tournera pas sous Xeon Phi. Il ne gère pas les exceptions FP.
    Et si tu compiles en x87, il faut rajouter une instruction nop flottante à la fin, parce que les exceptions sont envoyées lors de l'exécution de l'instruction flottante suivante (une histoire de câblage de copro externe dans les années 80).
    C'est horrible dans le sens ou balancer une exception dans un signal, je doute que ça soit super défini.
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  13. #2563
    Citation Envoyé par Tomaka17 Voir le message
    Viande = 1
    Feu = 2
    Viande cuite = 3
    Barre de fer = 4
    Charbon = 5
    Epée = 9

    Donc :
    Viande cuite + viande cuite + viande cuite = Epée
    Viande cuite + viande = Barre de fer
    Viande x5 = charbon
    Il aurait mieux fait d'utiliser des lettres dans son exemple de clef, cela marche mieux.
    Mais c'est un poil lourdingue et pas méga évolutif...

  14. #2564
    Citation Envoyé par rOut Voir le message
    C'est horrible dans le sens ou balancer une exception dans un signal, je doute que ça soit super défini.
    Non ça ne l'est pas vraiment en effet : cf section 18:10 du draft ou bien la doc de Sun Studio C++
    ou cette note pour HP aC++.

    Faut utiliser longjmp, C rules

  15. #2565
    Citation Envoyé par Grosnours Voir le message
    Il aurait mieux fait d'utiliser des lettres dans son exemple de clef, cela marche mieux.
    Mais c'est un poil lourdingue et pas méga évolutif...
    On se retrouve tout de même avec une condition par solution possible.

    Je pense en trifouillant que le dictionnaire devrait faire l'affaire. Je testerais ça.

    Merci pour vos réponses.
    Dernière modification par Aulren ; 23/11/2012 à 12h29.

  16. #2566
    Citation Envoyé par Tomaka17 Voir le message
    Viande = 1
    Feu = 2
    Viande cuite = 3
    Barre de fer = 4
    Charbon = 5
    Epée = 9

    Donc :
    Viande cuite + viande cuite + viande cuite = Epée
    Viande cuite + viande = Barre de fer
    Viande x5 = charbon
    Ouais c'est pas faux.

  17. #2567
    Citation Envoyé par Tomaka17 Voir le message
    Donc :
    Viande cuite + viande cuite + viande cuite = Epée
    Viande cuite + viande = Barre de fer
    Viande x5 = charbon

    Quel mauvais esprit, on peut employer des puissances de 2 pour les éléments de base et les combiner avec des OR, comme dans un bitfield (tant qu'on n'a pas besoin d'utiliser plusieurs instances du même objet).

    Comme ça on pourra avoir :
    Viande + Feu = Viande cuite
    Barre de fer + Charbon + Feu = Epée
    Epée + Viande - (Barre de fer + Charbon) = Viande cuite

  18. #2568
    Citation Envoyé par Møgluglu Voir le message

    Quel mauvais esprit, on peut employer des puissances de 2 pour les éléments de base et les combiner avec des OR, comme dans un bitfield (tant qu'on n'a pas besoin d'utiliser plusieurs instances du même objet).

    Comme ça on pourra avoir :
    Viande + Feu = Viande cuite
    Barre de fer + Charbon + Feu = Epée
    Epée + Viande - (Barre de fer + Charbon) = Viande cuite
    lol non uniquement des additions sans parenthèses avec si je t'ai bien compris la possibilité d'avoir plusieurs instances d'objet.

  19. #2569
    Après ça limite à 64 le nombre de composants de base. :cherche-un-reproche:

    Plus sérieusement ça peut pose d'autres problèmes. Par exemple :
    Viande = 1
    Pomme de terre = 2
    Feu = 4
    Viande cuite = 5
    Pomme de terre cuite = 6
    Menu = 7

    Le truc sympa c'est que tu peux faire directement :
    Viande + Pomme de terre + Feu = Menu

    Par contre, ça ça devrait pas être autorisé :
    Viande cuite + Pomme de terre = Menu (puisque la pomme de terre n'est pas cuite)

    Ou au contraire s'il veut interdire le "Viande + Pomme de terre + Feu", c'est à dire obliger le joueur à cuire séparément, ben il peut pas.

    En fait ta méthode c'est une méthode "développeur de jeu des années 80-90", où tu utilisais des systèmes ingénieux et super rapides, mais qui t'obligeaient à adapter tout ton game design à ces limitations.
    Rust fanboy

  20. #2570
    Citation Envoyé par Møgluglu Voir le message

    Quel mauvais esprit, on peut employer des puissances de 2 pour les éléments de base et les combiner avec des OR, comme dans un bitfield (tant qu'on n'a pas besoin d'utiliser plusieurs instances du même objet).

    Comme ça on pourra avoir :
    Viande + Feu = Viande cuite
    Barre de fer + Charbon + Feu = Epée
    Epée + Viande - (Barre de fer + Charbon) = Viande cuite
    Il y a des moyens sympathiques d'avoir des bitfields sans gaspiller de mémoire et avec des noms sympas ? Parce que je suppose que les enums sont limités à 64 bits. Donc à 64 objet élémentaires.

    ---------- Post added at 15h58 ---------- Previous post was at 15h57 ----------

    Ou alors tu associes à chaque composant de base un nombre premier, et ensuite il suffit de faire la décomposition en nombres premiers pour avoir la composition du craft !
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  21. #2571
    Citation Envoyé par rOut Voir le message
    Il y a des moyens sympathiques d'avoir des bitfields sans gaspiller de mémoire et avec des noms sympas ? Parce que je suppose que les enums sont limités à 64 bits. Donc à 64 objet élémentaires.
    En C++ t'as le controversé std::vector<bool> qui est un bitfield de taille "illimitée" (c'est à dire tout ce que peut contenir la mémoire quoi).
    Il est controversé parce que c'est une spécialisation de std::vector. Beaucoup de gens pensent qu'ils auraient dû laisser std::vector<bool> comme un std::vector normal, et nommer le bitfield autrement.

    Par contre la classe en elle même n'a aucun problème, tu peux parfaitement l'utiliser.
    Par exemple tu créé un enum tout simple de tes objets (avec des valeurs 0, 1, 2, 3, etc.) puis tu écris "bitfield[ITEMS_MEAT] = 0;" et ça mettra le bit correspondant à 0, sans toucher aux autres.
    Rust fanboy

  22. #2572
    Sinon il y a un truc intéressant, mais plus compliqué.
    http://www.wutka.com/dawg.html

    Mais ça permet de trouver facilement toutes les recettes possibles qui contiennent les ingrédients proposé par le joueur.
    Anything that can go wrong will go wrong.

  23. #2573
    Citation Envoyé par TheMothMan Voir le message
    Sinon il y a un truc intéressant, mais plus compliqué.
    http://www.wutka.com/dawg.html

    Mais ça permet de trouver facilement toutes les recettes possibles qui contiennent les ingrédients proposé par le joueur.


    Désolé
    Rust fanboy

  24. #2574
    Citation Envoyé par rOut Voir le message
    Il y a des moyens sympathiques d'avoir des bitfields sans gaspiller de mémoire et avec des noms sympas ? Parce que je suppose que les enums sont limités à 64 bits. Donc à 64 objet élémentaires.
    Un std::bitset<N> indexé par un enum. Tu gardes l'intérêt principal des bitsets, qui est de faire des opérations booléennes et des réductions (any, all).

  25. #2575
    Nan mais vous prenez pas la tête un dictionnaire et un switch feront l'affaire. Heureusement que je vous ai pas demandé un truc compliqué ^^

    Et certains éléments comme le feu seront à part du système de craft.

  26. #2576
    Citation Envoyé par Tomaka17 Voir le message
    Désolé
    Ben, pourquoi faire simple quand on peut faire compliqué.
    Anything that can go wrong will go wrong.

  27. #2577
    En fait ton article parle de "DAWG", d'où mon image du mème "yo dawg" :j'explique-mes-blagues:
    Rust fanboy

  28. #2578
    Encore un problème avec un exo du cours (on ne se moque pas ). Un convertisseur de chiffre romain :

    Code:
    def RomDec(R) :
        conv = {'C': 100, 'D': 500, 'I': 1, 'M': 1000, 'L': 50, 'V': 5, 'X': 10}
        R = [conv[x] for x in R.upper()]
        N = 0
        for k in range(len(R) - 1) :
            if R[k] < R[k + 1] : N -= R[k]
            else : N += R[k]
        N += R[-1]
        return N
    Je bloque sur la ligne : " for k in range(len(R) - 1) : ", ne comprenant pas pourquoi il est nécessaire de retirer un puis de le rajouter plus loin dans le code. Le prof explique ça comme ça :
    L'expression du prédicat Ri < Ri+1 empêche de coder ce traitement avec un simple for x in R, car alors il ne
    serait pas possible d'accéder au x suivant...
    Ce qui ne m'aide pas des masses, et python me retourne un list index out of range si je teste sans enlever 1 à len(R).

  29. #2579
    En fait, le code dans la boucle traite les éléments 2 par 2, en comparant chaque élément (à l'indice k) à celui qui le suit (k + 1), pour établir si sa valeur doit être ajoutée ou retranchée du total, ce qui est le principe de composition des nombres romains. Si tu ne fais pas s'arrêter la boucle à l'avant-dernier élément, l'indice k + 1 dépassera la limite du tableau quand la boucle arrivera sur le dernier élément.

    Le N += R[-1] permet d'ajouter le dernier élément, celui qui n'est justement pas traité par la boucle (et permet aussi de gérer les nombres romains composés d'une seule lettre par la même occasion, pusqu'ils ne passent pas par la boucle).

  30. #2580
    A chaque itération, tu veux regarder si l'élément courant est plus grand ou plus petit que celui qui suit, pour savoir si tu dois l'ajouter ou le retirer de la somme totale.
    Par exemple: CIX, tu dois ajouter C (C > I), puis retirer I (I < X), puis ajouter X.
    Ou encore: CXI, tu dois ajouter C (C > I), puis ajouter X (X > I), puis ajouter I.

    Tu dois donc avoir un autre élément après l'élément courant pour pouvoir faire la comparaison. Ce qui n'est pas le cas quand tu as atteint de le dernier élément. Il faut donc le traiter à part, à la fin et en l'ajoutant systématiquement à la somme.
    Dans le cas d'un nombre à un seul chiffre, il n'y a pas de comparaison à faire, la somme est égale au chiffre.

    Une manière de faire en trichant un peu serait d'ajouter un 0 à la fin de la liste, de manière à aider l'algorithme.

    Et plus simplement en une ligne :
    Code:
    RomDec = lambda R: sum([ n > m and n or -n for c in [{'C': 100, 'D': 500, 'I': 1, 'M': 1000, 'L': 50, 'V': 5, 'X': 10, '0': 0}] for n,m in [ (c[r], c[s]) for r,s in zip(list(R), list(R)[1:] + ['0']) ] ])
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

Page 86 sur 334 PremièrePremière ... 3676787980818283848586878889909192939496136186 ... DernièreDernière

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •