Rechercher
Connexion
Chatbox externe
Derniers sujets
Partenaires
TI-Planet | Espace-TI : Forum |
Faire un don à Tout-82...
Où va cet argent ?
Membres donateurs:- Persalteas (10€)
- Wistaro (5€)
- jo2geek (22€)
Les posteurs les plus actifs du mois
Aucun utilisateur |
Sauvegarder des données
4 participants
Sauvegarder des données
Sauvegarder des données, savoir si le programme a déjà été lancé, compresser des informations, tout est à votre portée!
Bonjour à tous !
Tout d'abord je sais que mon sujet n'est pas au bon endroit, mais en tant que simple membre je ne peux pas poster d'articles... Si un modo passe par là et qu'il le juge utile, se serait bien qu'il déplace le sujet vers la catégorie « Articles » si possible. Merci d'avance ! Problème réglé.
Vous voulez sauvegarder votre niveau dans un jeu ? Sauvegarder diverses données ? Ou encore réaliser une action seulement la première fois qu'on lance le programme ?
Alors vous êtes au bon endroit, car c'est ce que je vais essayer de vous apprendre !
Pour commencer, vous avez besoin de connaître les listes personnalisées, puisqu'on va devoir les utiliser . A cause de cela, malheureusement, il est impossible de le faire sur une Ti 82 (à moins d'utiliser une liste "basique" mais on est pas sur qu'un autre programme ne l'utilise pas du coup...)
Je tiens à préciser que certaines des astuces qui suivent m'ont été proposées par je ne me rappelle plus qui sur le forum de l'ancien tout 82. S'il y a déjà eut des articles à ce sujet, je ne les ai jamais lu...
1. Sauvegarder un meilleur score, ou une information qui doit être initialisée à 0
Pour mes explications, je vais prendre l'exemple d'un jeu de SNAKE.
On va considérer qu'on veut sauvegarder les 3 meilleurs scores.
Pour ce faire, nous allons stocker ces informations dans une liste personnalisée, LSNAKE par exemple. Les 3 meilleurs scores occuperont chacun un rang de la liste personnalisée.
Voilà maintenant vous savez comment sauvegarder vos meilleurs scores !
Tant que vous ne modifiez/supprimez pas la liste personnalisée, vos informations sont en (relative) sécurité
2. Savoir si un programme a déjà été lancé, et ainsi sauvegarder un niveau, ou une information qui doit être initialisée à une valeur non nulle
Imaginons maintenant que nous voulons sauvegarder le niveau le plus élevé qu'on a débloqué sur notre SNAKE.
Il suffit de faire comme pour les scores, me diriez vous : utiliser un terme de la liste LSNAKE pour simplement stocker le niveau.
Certes, mais un problème se pose très vite : on commence au niveau 1, or lorsqu'on créé la liste, si elle n'existe pas, tous les termes sont mis à 0... On pourrait considérer qu'en mémoire le niveau 1 vaut 0, le 2 vaudrait alors 1 etc, mais dans ce cas je ne pourrais pas vous apprendre ce que j'ai l'intention de dire, donc ça ne servirait à rien
La solution alternative est de pouvoir tester si le programme a déjà été lancé, et le cas échéant, initialiser les données qui ont besoin (le niveau à 1 par ex).
Remarque: Comme le signale Linka plus bas, on voit souvent des programmes nécessitant, pour être lancé la première fois, de lancer un autre programme qui va créer une liste personnalisée avec les valeurs initiales. Ceci est à éviter! En effet, il est vraiment peu pratique pour l'utilisateur de devoir lancer un autre programme la première fois qu'il veut l'utiliser! Utilisez plutôt ce que nous allons maintenant voir .
Réfléchissons un peu : il y a 2 choix possibles : soit le programme a été lancé, soit il ne l'a pas été.
Ce qu'il nous faudrait donc, c'est stocker une information qui contiendrait 1 (vrai) si le programme a déjà été lancé, et 0 sinon (puisque la liste sera initialisé avec des valeurs nulles si elle n'existait pas, ce qui nous convient parfaitement ! ).
On va alors fixer :
Codons sans plus tarder :
Petite remarque que fait Linka plus bas concernant les 83+:
3. Quelques remarques et optimisations par rapport aux codes précédents
A. Savoir si le programme a déjà été lancé à partir d'informations non nulles
A ce stade, on peut remarquer qu'en fait, le niveau ne vaudra jamais 0 (comme les meilleurs scores qui sont initialisés dans le code précèdent).
On peut donc s'en servir pour savoir si le jeu a déjà été lancé !
En effet, si le niveau vaut 0, c'est que la liste vient d'être initialisée, et sinon, que tout est ok, le jeu a déjà été lancé.
On peut donc faire :
B. Initialiser toutes les valeurs en une seule commande
Si vous avez plusieurs valeurs à initialiser, plutôt que de faire:
On peut remarquer que dans ce cas précis, où on stocke une liste dans une liste personnalisée, le nom de la liste suffit, ainsi, plutôt que de mettre LSNAKE on peut directement mettre SNAKE, la calto comprend qu'il s'agit d'une liste personnalisée nommée LSNAKE.
Par contre vous ne pouvez pas faire:
C. Compresser les données : Stocker plusieurs valeurs dans un seul terme de la liste
Dans un snake, on peut remarquer que notre score a un maximum qu'il ne peut pas dépasser.
En effet, l'écran fait 63*95=5985 pixels. Si on dessine un serpent avec des carrés de 3*3, avec un pixel entre chaque segment du serpent, on obtient un maximum de 5985/4/4=384 segments.
Ainsi, puisqu'on veut stocker 3 meilleurs scores, ça donne environ 400^3=64 000 000 possibilités maximum (on arrondi c'est pas important). On se rend donc compte qu'on peut stocker les 3 meilleurs scores, puisqu'il y a moins de 13 chiffres.
Donc, en s'y prenant bien, il est possible de stocker plusieurs informations dans le même terme de la liste.
Ici ce n'est certes pas très pratique (à cause des risques d'arrondis notamment comme le signale Linka plus bas), mais on peut faire mieux en fonction des informations à stocker.
Note: attention, si vous avez des nombres pouvant aller jusqu'à X, le facteur devra être de X+1.
Ex: Si vous voulez stocker plusieurs nombres compris entre 0 et 1, il faudra non pas multiplier par 1^N mais par 2^N:
Remarque: vous pouvez aussi stocker seulement des nombres négatifs en utilisant la méthode vue plus haut pour les nombres positifs (donc le terme de la liste utilisé sera négatif), mais attention à ne pas utiliser PartEnt (int en anglais), mais ent (iPart en français), sinon vous risquez d'être surpris par le résultat! Plus d'informations ici.
Autre remarque: stockez des nombres entiers avec ce système, et non des nombres décimaux (ou sinon faites attention à ne pas mélanger 2 données différentes, en fixant un maximum de chiffres).
Voici un exemple plus intéressant pour utiliser cette technique : vous avez un rpg et vous voulez sauvegarder si votre perso peut ou non utiliser le sort « feu » et le sort « glace ».
Et les nombres de signes opposés?
Il demeure un petit problème: comment faire pour stocker, dans un même terme de liste, des nombres de signes opposés?
Considérons que les nombres A et B à stocker dans C sont compris entre [ -9 ; 9].
Si on y réfléchi, il suffit d'ajouter 9 à cet intervalle pour que tous les nombres soient compris entre [ 0 ; 18], et soient ainsi tous positifs!
Il faut donc faire:
Et si l'intervalle ne commence pas à 0 on fait quoi?
Une dernière chose: Si vous avez des nombres compris entre 10 et 19 à compresser, faites comme pour les nombres dont le signe est inconnu:
Et si on a un intervalle du type [ -X ; -Y ] U [ Y ; X ] avec X>Y>0 ?
Il suffit de se se ramener à un intervalle [ -X + Y -1; X - Y + 1 ], et le tour est joué!
Ex: Soit A et B, compris dans l'intervalle [ -19 ; -10 ] U [ 10 ; 19 ] (je ne sais pas trop dans quel cas de figure vous pouvez avoir ça, mais on ne sait jamais )
Et pour un intervalle [ - V ; -W ] U [ X ; Y ] où X, Y, V et W >= 0 ?
Eh bien c'est la même chose en fait .
On se ramène à l'intervalle [ -V + W ; Y - X + 1 ]
Ex: Soit A et B compris entre [ -19 ; -10 ] U [ 20 ; 29 ] (notez que je ne sais toujours pas comment vous pouvez vous retrouver dans un cas pareil, mais je donne l'astuce à titre indicatif)
Dernière remarque: avec cette technique, on peut même compresser au maximum des nombres compris dans des réunions de 3, 4 ou 5 intervalles ! (voire même plus, mais là je crois que vous ne vous retrouverez définitivement jamais dans un cas pareil ): Il suffit de réduire progressivement le nombres d'intervalles dans la réunion considérée, comme on l'a fait plus haut pour passer de 2 à 1 intervalle.
Voilà vous savez maintenant comment utiliser les listes personnalisées pour sauvegarder tous types de données (en y réfléchissant un peu vous pouvez très bien stocker le nom du joueur, le mana, la vie, le niveau, des nombres négatifs, positifs, faire des intros si on y joue pour la première fois...).
La seule limite sera votre imagination !
Si vous avez des questions, suggestions, conseils, n'hésitez pas
PS:Merci à Linka pour son aide !
Je n'ai pas testé tous mes codes, si vous voyez une erreur, signalez là.
Bonjour à tous !
Vous voulez sauvegarder votre niveau dans un jeu ? Sauvegarder diverses données ? Ou encore réaliser une action seulement la première fois qu'on lance le programme ?
Alors vous êtes au bon endroit, car c'est ce que je vais essayer de vous apprendre !
Pour commencer, vous avez besoin de connaître les listes personnalisées, puisqu'on va devoir les utiliser . A cause de cela, malheureusement, il est impossible de le faire sur une Ti 82 (à moins d'utiliser une liste "basique" mais on est pas sur qu'un autre programme ne l'utilise pas du coup...)
Je tiens à préciser que certaines des astuces qui suivent m'ont été proposées par je ne me rappelle plus qui sur le forum de l'ancien tout 82. S'il y a déjà eut des articles à ce sujet, je ne les ai jamais lu...
1. Sauvegarder un meilleur score, ou une information qui doit être initialisée à 0
Pour mes explications, je vais prendre l'exemple d'un jeu de SNAKE.
On va considérer qu'on veut sauvegarder les 3 meilleurs scores.
Pour ce faire, nous allons stocker ces informations dans une liste personnalisée, LSNAKE par exemple. Les 3 meilleurs scores occuperont chacun un rang de la liste personnalisée.
- Code:
3->dim(LSNAKE //Grâce à cette instruction, si la liste n'existait pas, elle est créée, et remplie de 0, sinon elle est juste redimensionnée si besoin est (les cases manquantes étant remplies de 0)
//Le code de notre jeu
//Ici on considère que notre score est stocké dans S
For(A,1,3 //3 meilleurs scores
If S>LSNAKE(A //Nouveau meilleur Aème score
Then
LSNAKE(A->B //On récupère l'ancien Aème score
S->LSNAKE(A //On sauvegarde le nouveau Aème meilleur score
B->S //On charge le score déclassé, pour permettre un « décalage » des scores
End
End
Voilà maintenant vous savez comment sauvegarder vos meilleurs scores !
Tant que vous ne modifiez/supprimez pas la liste personnalisée, vos informations sont en (relative) sécurité
2. Savoir si un programme a déjà été lancé, et ainsi sauvegarder un niveau, ou une information qui doit être initialisée à une valeur non nulle
Imaginons maintenant que nous voulons sauvegarder le niveau le plus élevé qu'on a débloqué sur notre SNAKE.
Il suffit de faire comme pour les scores, me diriez vous : utiliser un terme de la liste LSNAKE pour simplement stocker le niveau.
Certes, mais un problème se pose très vite : on commence au niveau 1, or lorsqu'on créé la liste, si elle n'existe pas, tous les termes sont mis à 0... On pourrait considérer qu'en mémoire le niveau 1 vaut 0, le 2 vaudrait alors 1 etc, mais dans ce cas je ne pourrais pas vous apprendre ce que j'ai l'intention de dire, donc ça ne servirait à rien
La solution alternative est de pouvoir tester si le programme a déjà été lancé, et le cas échéant, initialiser les données qui ont besoin (le niveau à 1 par ex).
Remarque: Comme le signale Linka plus bas, on voit souvent des programmes nécessitant, pour être lancé la première fois, de lancer un autre programme qui va créer une liste personnalisée avec les valeurs initiales. Ceci est à éviter! En effet, il est vraiment peu pratique pour l'utilisateur de devoir lancer un autre programme la première fois qu'il veut l'utiliser! Utilisez plutôt ce que nous allons maintenant voir .
Réfléchissons un peu : il y a 2 choix possibles : soit le programme a été lancé, soit il ne l'a pas été.
Ce qu'il nous faudrait donc, c'est stocker une information qui contiendrait 1 (vrai) si le programme a déjà été lancé, et 0 sinon (puisque la liste sera initialisé avec des valeurs nulles si elle n'existait pas, ce qui nous convient parfaitement ! ).
On va alors fixer :
- Code:
LSNAKE(1) = 1 si prgm déjà lancé, 0 sinon
LSNAKE(2) = niveau
LSNAKE(3) = Meilleur score 1
LSNAKE(4) = Meilleur score 2
LSNAKE(5) = Meilleur score 3
Codons sans plus tarder :
- Code:
5->dim(LSNAKE //Grâce à cette instruction, si la liste n'existait pas, elle est créée, et remplie de 0
If non(LSNAKE(1 //Le premier terme contient 0 si le programme n'a jamais été lancé, et 1 sinon
Then
1->LSNAKE(1 //On sauvegarde le fait qu'on a déjà lancé le prgm
1->LSNAKE(2 //Niveau 1
10->LSNAKE(3 //Meilleur score 1 vaut 10 dès le début
7->LSNAKE(4 //Meilleur score 2 vaut 7 dès le début
5->LSNAKE(5 //Meilleur score 3 vaut 5 dès le début
//On peut aussi faire d'autres actions (une petite intro au jeu, afficher les règles, etc)
End
//Le code de notre jeu
//Gestion des meilleurs scores
For(A,3,5 //Ne pas oublier de modifier le numéro des termes des meilleurs scores
If S>LSNAKE(A
Then
LSNAKE(A->B
S->LSNAKE(A
B->S
End
End
Petite remarque que fait Linka plus bas concernant les 83+:
Linkakro a écrit:Sâchez que la ti83plus et ses successeurs supportent la dimension nulle des listes. Ainsi il suffit que la liste soit définie, même si elle est vide, pour savoir s'il faut initialiser.
Toutefois l'économie de mémoire et de méthode n'est pas particulièrement intéressante. Elle permet juste de se passer dans tous les cas du terme de contrôle de l'initialisation (le premier terme dans les exemples partie 2 et 3)
- Code:
// initial
If non(dim(lSNAKE
Then
// création
End
////////
//nettoyage
EffListe lSNAKE
Les bribes de code ci-dessus dans une ti83plus pourront remplacer la méthode présentée précédemment avec le premier terme même si on traite des données qui peuvent être nulles. Sur un modèle tel que 82stat, il faudra utiliser une des méthodes du tutoriel.
3. Quelques remarques et optimisations par rapport aux codes précédents
A. Savoir si le programme a déjà été lancé à partir d'informations non nulles
A ce stade, on peut remarquer qu'en fait, le niveau ne vaudra jamais 0 (comme les meilleurs scores qui sont initialisés dans le code précèdent).
On peut donc s'en servir pour savoir si le jeu a déjà été lancé !
En effet, si le niveau vaut 0, c'est que la liste vient d'être initialisée, et sinon, que tout est ok, le jeu a déjà été lancé.
On peut donc faire :
- Code:
4->dim(LSNAKE
If non(LSNAKE(1 //Le premier terme contient 0 si le programme n'a jamais été lancé, et le niveau sinon
Then
1->LSNAKE(1 //Niveau 1, on a lancé le prgm
End
//Le code de notre jeu
//Gestion des meilleurs scores
For(A,2,4 //Ne pas oublier de modifier le numéro des termes des meilleurs scores
If S>LSNAKE(A
Then
LSNAKE(A->B
S->LSNAKE(A
B->S
End
End
B. Initialiser toutes les valeurs en une seule commande
Si vous avez plusieurs valeurs à initialiser, plutôt que de faire:
- Code:
1->LSNAKE(1 //On sauvegarde le fait qu'on a déjà lancé le prgm
1->LSNAKE(2 //Niveau 1
10->LSNAKE(3 //Meilleur score 1 vaut 10 dès le début
7->LSNAKE(4 //Meilleur score 2 vaut 7 dès le début
5->LSNAKE(5 //Meilleur score 3 vaut 5 dès le début
- Code:
{1,1,10,7,5->SNAKE
On peut remarquer que dans ce cas précis, où on stocke une liste dans une liste personnalisée, le nom de la liste suffit, ainsi, plutôt que de mettre LSNAKE on peut directement mettre SNAKE, la calto comprend qu'il s'agit d'une liste personnalisée nommée LSNAKE.
Par contre vous ne pouvez pas faire:
- Code:
1->SNAKE(1 //Ne fonctionne pas!
//Alors que
L1->SNAKE //Fonctionne!
C. Compresser les données : Stocker plusieurs valeurs dans un seul terme de la liste
Dans un snake, on peut remarquer que notre score a un maximum qu'il ne peut pas dépasser.
En effet, l'écran fait 63*95=5985 pixels. Si on dessine un serpent avec des carrés de 3*3, avec un pixel entre chaque segment du serpent, on obtient un maximum de 5985/4/4=384 segments.
Ainsi, puisqu'on veut stocker 3 meilleurs scores, ça donne environ 400^3=64 000 000 possibilités maximum (on arrondi c'est pas important). On se rend donc compte qu'on peut stocker les 3 meilleurs scores, puisqu'il y a moins de 13 chiffres.
Donc, en s'y prenant bien, il est possible de stocker plusieurs informations dans le même terme de la liste.
- Code:
//Soit A, B, C et D les 4 meilleurs scores à sauvegarder
A400^2+B400+C+D/400->LSNAKE(3
//Maintenant on peut restaurer comme suit: (code donné par Linka plus bas)
LSNAKE(3->X //Pour gagner un peu de place
partEnt(Rép/400^2->A
partEnt((X-400A)/400->B
partEnt(X-B400-A400^2->C
partEnt((X-C-B400-A400^2)*400->D
{A,B,C,D
Ici ce n'est certes pas très pratique (à cause des risques d'arrondis notamment comme le signale Linka plus bas), mais on peut faire mieux en fonction des informations à stocker.
Note: attention, si vous avez des nombres pouvant aller jusqu'à X, le facteur devra être de X+1.
Ex: Si vous voulez stocker plusieurs nombres compris entre 0 et 1, il faudra non pas multiplier par 1^N mais par 2^N:
- Code:
A*2^3+B*2²+C*2+D
Remarque: vous pouvez aussi stocker seulement des nombres négatifs en utilisant la méthode vue plus haut pour les nombres positifs (donc le terme de la liste utilisé sera négatif), mais attention à ne pas utiliser PartEnt (int en anglais), mais ent (iPart en français), sinon vous risquez d'être surpris par le résultat! Plus d'informations ici.
Autre remarque: stockez des nombres entiers avec ce système, et non des nombres décimaux (ou sinon faites attention à ne pas mélanger 2 données différentes, en fixant un maximum de chiffres).
Voici un exemple plus intéressant pour utiliser cette technique : vous avez un rpg et vous voulez sauvegarder si votre perso peut ou non utiliser le sort « feu » et le sort « glace ».
- Code:
1->dim(LPOUV
//On restaure les pouvoirs
partEnt(LPOUV(1->A
2partDéc(LPOUV(1->B
//Code du jeu
//Sauvegarde des sorts (on considère que si A=1 alors on peut utiliser « feu», et que si B=1 on peut utiliser « glace», avec sinon respectivement A=0 et B=0)
A+B/2->LPOUV(1
- Code:
LPOUV(1)=0.0 « feu » désactivé ; « glace » désactivé ;
LPOUV(1)=1.0 « feu » activé ; « glace » désactivé ;
LPOUV(1)=0.5 « feu » désactivé ; « glace » activé ;
LPOUV(1)=1.5 « feu » activé ; « glace » activé ;
Et les nombres de signes opposés?
Il demeure un petit problème: comment faire pour stocker, dans un même terme de liste, des nombres de signes opposés?
Considérons que les nombres A et B à stocker dans C sont compris entre [ -9 ; 9].
Si on y réfléchi, il suffit d'ajouter 9 à cet intervalle pour que tous les nombres soient compris entre [ 0 ; 18], et soient ainsi tous positifs!
Il faut donc faire:
- Code:
//On stocke:
19(A+9)+B+9->C
//On récupère:
-9+PartEnt(C/19->A
C-19(A+9->B
Et si l'intervalle ne commence pas à 0 on fait quoi?
Une dernière chose: Si vous avez des nombres compris entre 10 et 19 à compresser, faites comme pour les nombres dont le signe est inconnu:
- Code:
//Plutôt que de faire:
A*20+B->C
ParEnt(C/20->A
C-20A->B
//Faites plutôt:
(A-10)*20+B-10->C
10+ParEnt(C/20->A
C-20(A-10)+10->B
Et si on a un intervalle du type [ -X ; -Y ] U [ Y ; X ] avec X>Y>0 ?
Il suffit de se se ramener à un intervalle [ -X + Y -1; X - Y + 1 ], et le tour est joué!
Ex: Soit A et B, compris dans l'intervalle [ -19 ; -10 ] U [ 10 ; 19 ] (je ne sais pas trop dans quel cas de figure vous pouvez avoir ça, mais on ne sait jamais )
- Code:
//Pour stocker:
//Je détaille un peu plus pour que vous puissiez me suivre:
A+9((A<0)-(A>0->A //Maintenant A est compris entre [ -10 ; -1 ] U [ 1 ; 10 ], soit [ -10 ; 10 ], ce qu'on sait traiter
B+9((B<0)-(B>0->B
21(A+10)+B+10->C
//Pour restaurer:
-10+PartEnt(C/21->A
C-21(A+10->B //A et B sont entre [ -10 ; 10 ]
A-9((A<0)-(A>0->A
B-9((B<0)-(B>0->B
Et pour un intervalle [ - V ; -W ] U [ X ; Y ] où X, Y, V et W >= 0 ?
Eh bien c'est la même chose en fait .
On se ramène à l'intervalle [ -V + W ; Y - X + 1 ]
Ex: Soit A et B compris entre [ -19 ; -10 ] U [ 20 ; 29 ] (notez que je ne sais toujours pas comment vous pouvez vous retrouver dans un cas pareil, mais je donne l'astuce à titre indicatif)
- Code:
//On stocke:
A+10(A<0)-19(A>0->B //On a a compris entre [ -9 ; 10 ]
B+10(B<0)-19(B>0->B
20(A+9)+B+9->C
//Pour restaurer:
-9+PartEnt(C/20->A
C-20(A+9->B //A et B sont entre [ -9 ; 10 ]
A-10(A<=0)+19(A>0->B
B-10(B<=0)+19(B>0->B
Dernière remarque: avec cette technique, on peut même compresser au maximum des nombres compris dans des réunions de 3, 4 ou 5 intervalles ! (voire même plus, mais là je crois que vous ne vous retrouverez définitivement jamais dans un cas pareil ): Il suffit de réduire progressivement le nombres d'intervalles dans la réunion considérée, comme on l'a fait plus haut pour passer de 2 à 1 intervalle.
Voilà vous savez maintenant comment utiliser les listes personnalisées pour sauvegarder tous types de données (en y réfléchissant un peu vous pouvez très bien stocker le nom du joueur, le mana, la vie, le niveau, des nombres négatifs, positifs, faire des intros si on y joue pour la première fois...).
La seule limite sera votre imagination !
Si vous avez des questions, suggestions, conseils, n'hésitez pas
PS:Merci à Linka pour son aide !
Je n'ai pas testé tous mes codes, si vous voyez une erreur, signalez là.
Dernière édition par m@thieu41 le Jeu 8 Aoû 2013 - 12:44, édité 11 fois
m@thieu41- ----------------------
- Messages : 939
Points Concours : 65
Productivité : 47
Date d'inscription : 02/06/2013
Localisation : Nice, France
Calculatrice(s) :- TI-82 Stats.fr
. :
Re: Sauvegarder des données
Excellent, surtout considérant que c'est le premier tutoriel que je vois expliquer certaines choses.
De mon côté je n'ai jamais pris le temps de rédiger un tel recueuil. J'ai été tout seul à en parler (ou presque si je me trompe) pendant quelques années... Serait-ce moi qui t'en avais parlé par hasard ? En tout cas je pense que l'exemple est sorti d'une discussion récente du tout82 original, j'avais justement conseillé un détail après ton post.
Sais-tu que j'ai utilisé ces méthodes pour adapter le snake de Vibra à la Ti82stat ? Pour ne pas réécrire tous les usages de listes, je me suis contenté de copier les informations importantes si besoin dans des listes personnalisées, et leur gestion était soumise au premier terme d'une de ces listes. Je n'ai jamais pris le temps de le poster et c'est dommage.
J'avais déjà utilisé la compression par des bases puissances de 10 (10,100,0.1,...), mais je n'avais jamais pensé à utiliser d'autres bases (ici tu utilises 400). En général je redoute les erreurs de calculs qui viennent souvent avec des bases autres que 10.
J'en viens alors à une de mes remarques... car il y a des divisions.
Remarques
A mon humble avis :
- tu devrais mentionne rl'idée de tester l'état initial (première execution d'un programme) dans le nom de la partie 2.
- tu devrais écrire une remarque pour expliquer pourquoi on fait comme ça : Beaucoup trop de programmes nécessitent d'executer d'abord une commande d'initialisation manuellement (ou un autre programme). Cette initialisation manuelle est à bannir car elle n'est pas agréable pour l'utilisateur, qu'elle n'est pas évidente si le code source est sorti de son contexte, et qu'on pourrait peut-être rencontrer des problèmes plus grâves qu'une erreur dim invalid.
Rappelez vous que vous pouvez dans certains cas utiliser une affectation de la liste entière.
{1,0,N,999->lSNAKE
Rappelez vous que l'affectation supporte l'ommission du caractère Liste, il suffit de saisir le nom.
{1,0,N,999->SNAKE
C'est gentil de montrer une compression de base 400, mais comment on la relit ?
La méthode donnée pour 2 informations en base 10 est bien la plus simple, mais parlons de tout, voyons.
Il y a plusieurs méthodes générales avec divisions, certaines sont plus simples mais causent des arrondis, d'autres plus compliquées sont plus sûres... Vous pouvez souvent simplifier, les conditions ne sont pas toujours évidentes. Le fait d'avoir à la fois du suppérieur à 1 et de l'inférieur à 1 est une cause de complexité énorme sauf dans des cas très simples. Moi je me perd tout seul dans les méthodes, je vous en ferai une seule (quotient décroissant). Sinon on en a 4 principales, d'une part on récupère par ordre croissant ou décroissant, et d'autre part on recherche soit le quotient soit le reste. Quand vous utilisez diviseur*partdéc(X/diviseur), ce qui est courant, vous avez de grands risques d'arrondis si vous enchainez des calculs.
Sâchez que la ti83plus et ses successeurs supportent la dimension nulle des listes. Ainsi il suffit que la liste soit définie, même si elle est vide, pour savoir s'il faut initialiser.
Toutefois l'économie de mémoire et de méthode n'est pas particulièrement intéressante. Elle permet juste de se passer dans tous les cas du terme de contrôle de l'initialisation (le premier terme dans les exemples partie 2 et 3)
De mon côté je n'ai jamais pris le temps de rédiger un tel recueuil. J'ai été tout seul à en parler (ou presque si je me trompe) pendant quelques années... Serait-ce moi qui t'en avais parlé par hasard ? En tout cas je pense que l'exemple est sorti d'une discussion récente du tout82 original, j'avais justement conseillé un détail après ton post.
Sais-tu que j'ai utilisé ces méthodes pour adapter le snake de Vibra à la Ti82stat ? Pour ne pas réécrire tous les usages de listes, je me suis contenté de copier les informations importantes si besoin dans des listes personnalisées, et leur gestion était soumise au premier terme d'une de ces listes. Je n'ai jamais pris le temps de le poster et c'est dommage.
J'avais déjà utilisé la compression par des bases puissances de 10 (10,100,0.1,...), mais je n'avais jamais pensé à utiliser d'autres bases (ici tu utilises 400). En général je redoute les erreurs de calculs qui viennent souvent avec des bases autres que 10.
J'en viens alors à une de mes remarques... car il y a des divisions.
Remarques
A mon humble avis :
- tu devrais mentionne rl'idée de tester l'état initial (première execution d'un programme) dans le nom de la partie 2.
- tu devrais écrire une remarque pour expliquer pourquoi on fait comme ça : Beaucoup trop de programmes nécessitent d'executer d'abord une commande d'initialisation manuellement (ou un autre programme). Cette initialisation manuelle est à bannir car elle n'est pas agréable pour l'utilisateur, qu'elle n'est pas évidente si le code source est sorti de son contexte, et qu'on pourrait peut-être rencontrer des problèmes plus grâves qu'une erreur dim invalid.
Rappelez vous que vous pouvez dans certains cas utiliser une affectation de la liste entière.
{1,0,N,999->lSNAKE
Rappelez vous que l'affectation supporte l'ommission du caractère Liste, il suffit de saisir le nom.
{1,0,N,999->SNAKE
C'est gentil de montrer une compression de base 400, mais comment on la relit ?
La méthode donnée pour 2 informations en base 10 est bien la plus simple, mais parlons de tout, voyons.
Il y a plusieurs méthodes générales avec divisions, certaines sont plus simples mais causent des arrondis, d'autres plus compliquées sont plus sûres... Vous pouvez souvent simplifier, les conditions ne sont pas toujours évidentes. Le fait d'avoir à la fois du suppérieur à 1 et de l'inférieur à 1 est une cause de complexité énorme sauf dans des cas très simples. Moi je me perd tout seul dans les méthodes, je vous en ferai une seule (quotient décroissant). Sinon on en a 4 principales, d'une part on récupère par ordre croissant ou décroissant, et d'autre part on recherche soit le quotient soit le reste. Quand vous utilisez diviseur*partdéc(X/diviseur), ce qui est courant, vous avez de grands risques d'arrondis si vous enchainez des calculs.
- Code:
A400^2+B400+C+D/400->X
partEnt(X/400^2->A
partEnt((X-400A)/400->B
partEnt(X-B400-A400^2->C
partEnt((X-C-B400-A400^2)*400->D
{A,B,C,D
Sâchez que la ti83plus et ses successeurs supportent la dimension nulle des listes. Ainsi il suffit que la liste soit définie, même si elle est vide, pour savoir s'il faut initialiser.
Toutefois l'économie de mémoire et de méthode n'est pas particulièrement intéressante. Elle permet juste de se passer dans tous les cas du terme de contrôle de l'initialisation (le premier terme dans les exemples partie 2 et 3)
- Code:
// initial
If non(dim(lSNAKE
Then
// création
End
////////
//nettoyage
EffListe lSNAKE
Linkakro- ----------------------
- Messages : 533
Points Concours : 55
Productivité : 31
Date d'inscription : 30/07/2013
Localisation : origine région centre, puis perpignan
Calculatrice(s) :- TI-82 Stats.fr
. :
Re: Sauvegarder des données
Merci pour tes remarques, je vais modifier 2-3 truc
C'est en effet après avoir expliqué plus ou moins la même chose à rpgcreator et à 82statsfr sur l'ancien forum il n'y a pas longtemps que je me suis dis qu'il serait bien de faire un tuto à ce sujet.
C'est peut être de toi que j'avais appris ça je ne sais plus, mais alors tu expliquais à quelqu'un d'autre, parce que je ne m'en suis servis que très récemment, et je n'ai jamais eut besoin de tester si on avait déjà joué ou pas à un jeu.
C'est en effet après avoir expliqué plus ou moins la même chose à rpgcreator et à 82statsfr sur l'ancien forum il n'y a pas longtemps que je me suis dis qu'il serait bien de faire un tuto à ce sujet.
C'est peut être de toi que j'avais appris ça je ne sais plus, mais alors tu expliquais à quelqu'un d'autre, parce que je ne m'en suis servis que très récemment, et je n'ai jamais eut besoin de tester si on avait déjà joué ou pas à un jeu.
m@thieu41- ----------------------
- Messages : 939
Points Concours : 65
Productivité : 47
Date d'inscription : 02/06/2013
Localisation : Nice, France
Calculatrice(s) :- TI-82 Stats.fr
. :
Re: Sauvegarder des données
Sujet déplacé dans la section article, s'agissant plus d'un tutoriel.
blg_flg- Connaisseur
- Messages : 249
Points Concours : 45
Productivité : 6
Date d'inscription : 04/06/2013
Localisation : Pantruche
Calculatrice(s) :- TI-82 Stats.fr
. :
Re: Sauvegarder des données
Bien les changements ! Tu en as fais bien plus que mes remarques ! Surtout ta méthode de décalage des ensembles des termes qui est bien pensée.
J'ai rédigé ce message en plusieurs jours en espérant ne pas écrire de bêtise !
Je parlerai ici exclusivement des compressions.
+++++++++++++++++++++++++++++++++++++++++++++
Pour que le traitement de nombres tous négatifs marche, il faut utiliser iPart/ent. Alors que j'ai donné l'extraction avec partEnt. Il faut préciser et corriger nos deux messages. Je pense qu'on doit remplacer par ent et préciser la traduction et que les négatifs marcheront sans changer.
+++++++++++++++++++++++++++++++++++++++++++++
Tous les exemples utilisent des paires de variables de même domaine. Il faudrait à terme dans les exemples ne s'occuper du domaine que pour une seule variable à chaque fois.
Cependant j'ai commencé par commenter les codes actuels, je pense fournir plus tard une nouvelle rédaction des chapitres de compression, probablement par message privé pour ne pas faire de double dans le sujet.
=============================================
La compression est-elle indispensable ?
Je dirai non.
Cela permet d'utiliser en stockage une seule variable, quand :
- on veut effectuer une seule affectation pour l'ensemble
- on manque de mémoire
L'argument de la mémoire peut inciter à choisir les coefficients les plus étroits.
>>> Mais si la somme n'atteind pas la limite de 14 chiffres, (en pratique avec des entiers il suffit souvent de regarder le plus grand terme), on n'a pas besoin de resserrer les domaines.
Pour un nombre inférieur à 20 exclu, on ne sera pas obligé de multiplier le prochain ordre par 20.
20A+B ou 100A+B peuvent marcher aussi bien l'un que l'autre.
=============================================
Plus à propos des prévisions des ordres de grandeur
=============================================
Tu effectues l'opération de décalage en même temps que la compression/décompression sans le commenter.
>> je voudrais que ce soit indiqué, ou mieux que l'exemple utilise une variable intermédiaire.
Tu effectues le décalage opposé en même temps que la décompression, et tu te retrouves à mettre encore un décalage pour décompresser la variable suivante. Mauvaise idée.
>>>>Dans ces deux considérations, je préfère que les compression/décompressions soient séparées de tout le reste, même si les changements de domaines sont tous fais en même temps.
Tu introduit les chapitre en disant "on se ramène à l'intervalle...". Je demande que tu précises qu'on compose ensuite la transformation avec la méthode du chapitre correspondant à cet ensemble réduit.
Dans les deux chapitres cités, tu oublies le décalage de l'extraction de B, alors que tu la fais pour A.
ex premier : C-21(P+10->Q n'est pas bon, fais C-10-21(P+10->Q
Toujours dans les deux, tu décales A immédiatement après l'extraction pour ensuite faire l'opposé dans le calcul de B. Ce n'est pas judicieux !
-10+iPart(C/21->A // quotient-10->A
C-10-21(A+10->B // A+10=quotient ; C-10-21*quotient
Je donne des codes basés sur le cas symétrique, faites de même pour l'autre.
corrigé avec le décalage manquant
quitte à s'embêter à resserrer avant de compresser, je te conseillerais de décaler différemment positif et négatif pour les serrer dans un intervalle continu.
Je le montre pour le cas symétrique, mais ce devrait être une évidence pour l'autre puisqu'on a déjà vu l'idée de dilater différemment selon l'intervalle.
Encore une question de simplicité sans économie :
[-X;-Y]U[Y;X]
Alors que tu te contrains à resserrer dans [0;Y-1]U[Y+1;X+Y] (ou [0;X+Y-1] avec une de mes remarques)
Je propose de simplement ajouter X, afin de décaler en [0;X-Y]U[X+Y;2X].
Bien qu'on n'économise pas, on n'en a pas forcément besoin ! Cela dépend de la quantité qu'on rassemble.
Et si on manipulait les ensembles avec des produits et des divisions ?
Je pense le faire pour supporter notamment des nombres décimaux en conservant les algorithmes sur les entiers.
Pour toutes les conceptions en raisonnant sur les intervalles, pensez que zéro est toujours possible indépendamment des étendues avec des décimales.
=============================================
Tu as enlevé ton premier exemple de compression de paires de données et c'est dommage : cela illustrait l'usage simple de base 10 et fPart/iPart (sans divisions ennuyeuses contrairement à ma méthode générale), et généralement qu'on peut faire simple avec un bon choix.
Moi j'illustrerais le stockage de coordonnées d'un serpent. Avec chaque segment ayant deux coordonnées stockées dans un terme de liste.
Je placerais cela au début du chapitre de compression, suivi de l'exemple des feux, suivi enfin de mon code.
=============================================
Certes j'ai averti d'arrondis pour des calculs d'extraction, cependant :
1-j'ai exprès choisi le code qui doit être (selon moi) le plus exact pour des nombres entiers.
2-je suis obsédé comme persone par la précision, (notamment car j'ai des travaux limités par ça).
3-un arrondi de manque de chiffres et un arrondi de calcul peuvent se compenser : par exemple 3*fPart(4/3) donne bien 4 exactement (pas un affichage)
4-il peut arriver que des arrondis ne se voient pas : 4.99999999999999999999999 brut stocke 4.9999999999999 et affiche 5
Donc pas tant d'inquiétudes à se faire.
=============================================
On peut utiliser des coefficients irréguliers mais cela pose des problèmes :
-cela complique les prévisions des possibilités des variables.
-on ne peut plus forcément extraire avec des restes de division : c'est possible seulement si les coeffs sont multiples (300,100,20,1 marche par exemple quand 100,70,20,1 ne permet pas l'algorithme des restes)
Remarque : Dans un sens on peut économiser un maximum de place avec des coefficients irréguliers et strict nécessaire, et dans l'autre sens on peut choisir des coefficients plus larges que le strict nécessaire pour obtenir des coefficients multiples voire réguliers.
=============================================
Plus à propos des méthodes d'extraction que j'ai mentionné par le passé
J'ai rédigé ce message en plusieurs jours en espérant ne pas écrire de bêtise !
Je parlerai ici exclusivement des compressions.
+++++++++++++++++++++++++++++++++++++++++++++
Pour que le traitement de nombres tous négatifs marche, il faut utiliser iPart/ent. Alors que j'ai donné l'extraction avec partEnt. Il faut préciser et corriger nos deux messages. Je pense qu'on doit remplacer par ent et préciser la traduction et que les négatifs marcheront sans changer.
+++++++++++++++++++++++++++++++++++++++++++++
Tous les exemples utilisent des paires de variables de même domaine. Il faudrait à terme dans les exemples ne s'occuper du domaine que pour une seule variable à chaque fois.
Cependant j'ai commencé par commenter les codes actuels, je pense fournir plus tard une nouvelle rédaction des chapitres de compression, probablement par message privé pour ne pas faire de double dans le sujet.
=============================================
La compression est-elle indispensable ?
Je dirai non.
Cela permet d'utiliser en stockage une seule variable, quand :
- on veut effectuer une seule affectation pour l'ensemble
- on manque de mémoire
L'argument de la mémoire peut inciter à choisir les coefficients les plus étroits.
>>> Mais si la somme n'atteind pas la limite de 14 chiffres, (en pratique avec des entiers il suffit souvent de regarder le plus grand terme), on n'a pas besoin de resserrer les domaines.
Pour un nombre inférieur à 20 exclu, on ne sera pas obligé de multiplier le prochain ordre par 20.
20A+B ou 100A+B peuvent marcher aussi bien l'un que l'autre.
=============================================
Plus à propos des prévisions des ordres de grandeur
- Spoiler:
- Déjà, le nombre 0 est toujours correct. Ce qui intéresse vraiment est l'intervalle des valeurs non-nulles pour chaque donnée.
Je calcule le produit de la variable et du coefficient, et je cherche à ce que les ordres de grandeur des termes ne se chevauchent pas.
(une division peut donner les intervalles maximals à partir des coefficients)
Je m'organise en partant d'un coefficient initial 1 puis en choisissant de proche en proche des intervalles qui sont cohérents.
On peut viser plus large que le stricte nécessaire, tant qu'il reste de la place dans le stockage ensuite.
Vous pouvez vous organiser différemment, en particulier en changeant le coeff et l'ordre de départ. Mais je vous conseille vivement de faire comme moi.
D 0ou]1;19] ; coeff 1
C 0ou[2;4] ; 10C 0ou]20 ; 40] ; 19<20
B 0ou[1;2] ; 50B 0ou]50 ; 100] ; 40<50
A 1 < A ou A=0 : 100<200A ou A=0
200A+50B+10C+D->X
La somme peut occuper 0ou[1;10^14-1] classiquement.
Selon le poids faible en base 10 du nombre stocké, la marge peut être décalées de décades. par exemple [10;10^15-1] ou [0.1;10^13-1]
Pour connaître la limite de A, on regarde la fraction du maximum de X par le coeficient de A : (10^14-1)/200>=A
On pourra essayer aussi des variables décimales, mais on a intérêt pour bien prévoir (et calculer les divisions) à changer les domaines en entiers d'abord. C'est une de mes futures suggestions.
=============================================
- Spoiler:
- m@thieu41 a écrit:Et si on a un intervalle du type [ -X ; -Y ] U [ Y ; X ] avec X>Y>0 ?
Il suffit de se se ramener à un intervalle [ -X + Y -1; X - Y + 1 ], et le tour est joué!
Ex: Soit A et B, compris dans l'intervalle [ -19 ; -10 ] U [ 10 ; 19 ] (je ne sais pas trop dans quel cas de figure vous pouvez avoir ça, mais on ne sait jamais )- Code:
//Pour stocker:
//Je détaille un peu plus pour que vous puissiez me suivre:
A+9((A<0)-(A>0->A //Maintenant A est compris entre [ -10 ; -1 ] U [ 1 ; 10 ], soit [ -10 ; 10 ], ce qu'on sait traiter
B+9((B<0)-(B>0->B
21(A+10)+B+10->C
//Pour restaurer:
-10+PartEnt(C/21->A
C-21(A+10->B //A et B sont entre [ -10 ; 10 ]
A-9((A<0)-(A>0->A
B-9((B<0)-(B>0->B
Eh bien c'est la même chose en fait .
On se ramène à l'intervalle [ -V + W ; Y - X + 1 ] Et on fait
Ex: Soit A et B compris entre [ -19 ; -10 ] U [ 20 ; 29 ] (notez que je ne sais toujours pas comment vous pouvez vous retrouver dans un cas pareil, mais je donne l'astuce à titre indicatif)- Code:
//On stocke:
A+10(A<0)-19(A>0->B //On a a compris entre [ -9 ; 10 ]
B+10(B<0)-19(B>0->B
20(A+9)+B+9->C
//Pour restaurer:
-9+PartEnt(C/20->A
C-20(A+9->B //A et B sont entre [ -9 ; 10 ]
A-10(A<=0)+19(A>0->B
B-10(B<=0)+19(B>0->B
Tu effectues l'opération de décalage en même temps que la compression/décompression sans le commenter.
>> je voudrais que ce soit indiqué, ou mieux que l'exemple utilise une variable intermédiaire.
Tu effectues le décalage opposé en même temps que la décompression, et tu te retrouves à mettre encore un décalage pour décompresser la variable suivante. Mauvaise idée.
>>>>Dans ces deux considérations, je préfère que les compression/décompressions soient séparées de tout le reste, même si les changements de domaines sont tous fais en même temps.
Tu introduit les chapitre en disant "on se ramène à l'intervalle...". Je demande que tu précises qu'on compose ensuite la transformation avec la méthode du chapitre correspondant à cet ensemble réduit.
Dans les deux chapitres cités, tu oublies le décalage de l'extraction de B, alors que tu la fais pour A.
ex premier : C-21(P+10->Q n'est pas bon, fais C-10-21(P+10->Q
Toujours dans les deux, tu décales A immédiatement après l'extraction pour ensuite faire l'opposé dans le calcul de B. Ce n'est pas judicieux !
-10+iPart(C/21->A // quotient-10->A
C-10-21(A+10->B // A+10=quotient ; C-10-21*quotient
Je donne des codes basés sur le cas symétrique, faites de même pour l'autre.
corrigé avec le décalage manquant
- Code:
A+9((A<0)-(A>0->A // A [-19;-10]U[10;19] devient [-10;-1]U[1;10] // on resserre
B+9((B<0)-(B>0->B
21(A+10)+B+10->C // on décale en [0;9]U[11;20] puis compresse
-10+iPart(C/21->A // on extrait et décale immédiatement
C-10-21(A+10->B // ces variables A et B sont dans [-10;-1]U[1;10]
// on avait ci-dessus besoin de décaler en A+10 car on a fait -10 juste avant, pas judicieux
A-9((A<0)-(A>0->A // on dilate en [-19;-10]U[10;19]
B-9((B<0)-(B>0->B
- Code:
A+10+9((A<0)-(A>0->P // A [-19;-10]U[10;19] devient [-10;-1]U[1;10] puis [0;9]U[11;20] // on serre avec +9(...) et décale avec +10.
B+10+9((B<0)-(B>0->Q
21P+Q->C // on compresse
iPart(C/21->P // on extrait
C-21P->Q //P et Q sont dans [0;9]U[11;20]
P-10-9((P<0)-(P>0->A // on décale puis dilate
Q-10-9((Q<0)-(Q>0->B
Je n'ai pas séparé le décalage et la dilatation, ce n'est pas développé le plus possible, mais cela résout l'oubli du décalage de B et est quand même plus clair selon moi.
- Code:
A+9((A<0)-(A>0->M // A [-19;-10]U[10;19] devient M [-10;-1]U[1;10] // on serre
B+9((B<0)-(B>0->N
M+10->P // on décale [0;9]U[11;20]
N+10->Q
21P+Q->C // on compresse
iPart(C/21->P // on extrait
C-21P->Q //P et Q sont dans [0;9]U[11;20]
P-10->M // on décale
Q-10->N
M-9((M<0)-(M>0->A // on dilate
N-9((N<0)-(N>0->B
quitte à s'embêter à resserrer avant de compresser, je te conseillerais de décaler différemment positif et négatif pour les serrer dans un intervalle continu.
Je le montre pour le cas symétrique, mais ce devrait être une évidence pour l'autre puisqu'on a déjà vu l'idée de dilater différemment selon l'intervalle.
- Code:
A+10(A<0)-9(A>0->M // A [-19;-10]U[10;19] devient M [-9;10] // on serre
B+10((B<0)-9(B>0->N
M+9->P // on décale [0;19]
N+9->Q
21P+Q->C // on compresse
iPart(C/21->P // on extrait
C-21P->Q //P et Q sont dans [0;19]
P-9->M // on décale
Q-9->N
M-10(M<0)+9(M>0->A // on dilate
N-10(N<0)+9(N>0->B
Encore une question de simplicité sans économie :
[-X;-Y]U[Y;X]
Alors que tu te contrains à resserrer dans [0;Y-1]U[Y+1;X+Y] (ou [0;X+Y-1] avec une de mes remarques)
Je propose de simplement ajouter X, afin de décaler en [0;X-Y]U[X+Y;2X].
Bien qu'on n'économise pas, on n'en a pas forcément besoin ! Cela dépend de la quantité qu'on rassemble.
- Code:
// [-19;-10]U[10;19]
A+19->P // on décale en [0;9]U[29;38]
B+19->Q
39P+Q->C // on compresse
iPart(C/21->P // on extrait
C-21P->Q
P-19->A // on décale
Q-19->B
Et si on manipulait les ensembles avec des produits et des divisions ?
Je pense le faire pour supporter notamment des nombres décimaux en conservant les algorithmes sur les entiers.
Pour toutes les conceptions en raisonnant sur les intervalles, pensez que zéro est toujours possible indépendamment des étendues avec des décimales.
- Spoiler:
- sans entrer dans des détails, exemple pour le changement d'une variable
A dans 0ou[0.1;0.9]
10A 0ou[1;9]
// B est ici entière et 10A=Z<20B
10A->Z
Z+20B->C
iPart(C/20->B
C-20B->Z
Z/10->A
=============================================
Tu as enlevé ton premier exemple de compression de paires de données et c'est dommage : cela illustrait l'usage simple de base 10 et fPart/iPart (sans divisions ennuyeuses contrairement à ma méthode générale), et généralement qu'on peut faire simple avec un bon choix.
Moi j'illustrerais le stockage de coordonnées d'un serpent. Avec chaque segment ayant deux coordonnées stockées dans un terme de liste.
Je placerais cela au début du chapitre de compression, suivi de l'exemple des feux, suivi enfin de mon code.
=============================================
Certes j'ai averti d'arrondis pour des calculs d'extraction, cependant :
1-j'ai exprès choisi le code qui doit être (selon moi) le plus exact pour des nombres entiers.
2-je suis obsédé comme persone par la précision, (notamment car j'ai des travaux limités par ça).
3-un arrondi de manque de chiffres et un arrondi de calcul peuvent se compenser : par exemple 3*fPart(4/3) donne bien 4 exactement (pas un affichage)
4-il peut arriver que des arrondis ne se voient pas : 4.99999999999999999999999 brut stocke 4.9999999999999 et affiche 5
Donc pas tant d'inquiétudes à se faire.
=============================================
On peut utiliser des coefficients irréguliers mais cela pose des problèmes :
-cela complique les prévisions des possibilités des variables.
-on ne peut plus forcément extraire avec des restes de division : c'est possible seulement si les coeffs sont multiples (300,100,20,1 marche par exemple quand 100,70,20,1 ne permet pas l'algorithme des restes)
Remarque : Dans un sens on peut économiser un maximum de place avec des coefficients irréguliers et strict nécessaire, et dans l'autre sens on peut choisir des coefficients plus larges que le strict nécessaire pour obtenir des coefficients multiples voire réguliers.
=============================================
Plus à propos des méthodes d'extraction que j'ai mentionné par le passé
- Spoiler:
- Cas particulier : avec la base 10 on peut facilement déplacer la virgule et supprimmer ce qui dépasse sans réfléchir à des algorithmes.
100A+B+C/100->X
iPart(X/100)->A
iPart(100fPart(X/100))->B // j'enlève 100A avec 100fPart(X/100) puis j'enlève C/100
100fPart(X)->C
Pour tout le reste on généralise avec des divisions euclidiennes pour isoler des termes un par un depuis une extrémité.
Les restes donnent les variables dans l'ordre des coefficients croissants et les quotients donnent le contraire.
Problème : les restes nécessitent absoluement des coefficients au moins multiples. Par exemple 100,10,1 ou encore 1000,200,20,1.- Spoiler:
- Cette méthode nécessite que les coefficients soient multiples.
Si on essayait avec des coefficients non-multiples, alors des termes d'ordres forts seraient inclus dans le reste l'ordre faible ou irrécupérables.
Par exemple a=3x+2y+z, alors diviser par 2 causerait :
-si x est impair : a=x+2x+2y+z=x+2(x+y)+z
-si x est pair : a=3*2j+2y+z=2(3j+y)+z
Ce qui ne permet pas d'isoler z ni les autres car soit les variables x et autres poids forts sont détruits soit il en reste des pas factorisés.
Au final on ne peut pas factoriser et isoler lorsque les coefficients ne sont pas multiples, donc l'algorithme ne marche plus.
Remarque : on a déjà supposé en créant la méthode que y sera inférieur à son coeff, ici 2, donc pas de question de parité/multiplicité à se poser
Remarque : des variables nulles par hasard peuvent éviter le problème, mais cela ne le résout pas dans tous les cas de variables
Les fonctions :
quotient(a/b)=iPart(a/b) // ne pas utiliser int ni partEnt si négatif
reste(a/b)=a-b*quotient(a/b)=a-b*iPart(a/b)
Et la cause d'arrondi la plus flagrante (même si pas systématique): reste(a/b)~~b*fPart(a/b)
Ajoûtez une fonction d'arrondi si vous voulez être tranquille.
Les algorithmes :
-quotient : un quotient par un coeff donne le terme le plus grand, puis on le soustrait et on recommence
-reste récurrent (le grand classique) : on divise par le rapport entre deux coeffs (si c'est régulier, c'est la base, par exemple 10 pour 100,10,1), le reste donne le terme le plus petit et le quotient sera divisé la fois suivante
-reste systématique : fait des restes comme le quotient, cela donne les termes du coeff le plus petit au plus grand.
Rappel : si les coefficients ne sont pas multiples, on ne peut pas utiliser les restes.
On peut utiliser des intermédiaires de calculs pour ne pas recalculer. Ce n'est pas toujours important.
1. les restes et les quotient sont liés entre eux : a=bq+r implique q=(a-r)/b et r=a-bq, mais on risque de perturber l'un avec l'autre quand on veut les deux. (CF "reste récurrent boucle", cela le montre en restant lisible)
2. des choses seraient sinon imbriquées et parfois illisibles.
2.1. Plutôt que de faire f(a-b) puis plus tard f(a-b-c) on peut faire f(a-b)->p:f(p):p-c->p:f(p) pour tenter d'économiser de la vitesse, mais c'est superflu.
2.2. par exemple quotient2=((dividende1-reste1)/diviseur1-reste2)/diviseur2 est illisible et demande des intermédiaires pour être lisible. (ou bien une boucle)
Je poserai en priorité les calculs de restes avec fPart (malgré ma méfiance, c'est clair) et les calculs de quotient avec iPart.
Je préciserai quelque fois avec q=(a-r)/b ou r=a-bq qui peuvent gagner du temps, et j'averti en même temps de quelques besoins suplémentaires.
Le dernier terme à trouver peut être calculé plus simplement indépendamment de la méthode.
quotient (sans intermédiaire) // que j'ai déjà donné et conseillé
1000A+100B+10C+D->X
iPart(X/1000)->A
iPart((X-1000A)/100)->B
iPart((X-1000A-100B)/10)->C
D-1000A-100B-10C->D // je me passe de fraction et iPart pour le coeff 1
quotient (avec intermédiaires Q // juste pour l'exemple de ce que je veux dire)
1000A+100B+10C+D->X
iPart(X/1000)->A
X-1000A->Y
iPart(Y/100)->B
Y-100B->Y
iPart((X-1000A-100B)/10)->C
Y-10C->D
reste récurrent (avec intermédiaire Q) // cela fait comme la boucle en évitant d'imbriquer
1000A+100B+10C+D->X
10fPart(X/10)->D
iPart(X/10)->Q
10fPart(Q/10)->C
iPart(Q/10)->Q
10fPart(Q/10)->B
iPart(Q/10)->A
Ci-dessus on pourrais calculer iPart(dividende/diviseur)=quotient=(dividende-reste)/diviseur
reste récurrent avec boucle (et intermédiaires Q)
//la boucle est intéressante mais demande une liste ou des tests qui gâchent tout
// avec variante de calcul et mise en relation de reste et quotient qui en découle
1000A+100B+10C+D->X
X->Q
0->W
Repeat Q=0
W+1->W
10fPart(Q/10)->Y // Q-10iPart(Q/10)->Y // iPart(Q/10)->Z
iPart(Q/10)->Q // iPart(Q/10)->Q // Q-10Z->Y
// // Z->Q
If W=1:Y->D
If W=2:Y->C
If W=3:Y->B
If W=4:Y->A
End
reste systématique
1000A+100B+10C+D->X
10fPart(X/10)->D
10fPart((X-D)/100)->C
10fPart((X-D-C10)/1000)->B
(X-D-C10-B100)/1000->A // pas un reste, c'est pour faire plus simple
####### variantes en coeffs irréguliers, les restes marchent parce que j'ai pris des coeffs multiples
quotient
1000A+200B+20C+D->X
iPart(X/1000)->A
iPart((X-1000A)/200)->B
iPart((X-1000A-100B)/20)->C
D-1000A-200B-20C->D
reste récurrent sans fPart (mais coeffs multiple !!! sinon marche pas)
1000A+200B+20C+D->X
X-20*iPart(X/20)->D
iPart(X/20)->Q
(Q-200iPart(Q/200))/20->C // formule reste/coeff
iPart(Q/200)->Q
(Q-1000iPart(Q/1000))/200->B
iPart(Q/1000)->A
reste récurrent avec fPart (mais coeffs multiple !!! sinon marche pas)
// j'ai transformé en fPart et appliqué la fraction des coeffs
1000A+200B+20C+D->X
20fPart(X/20)->D // 20/1=20
iPart(X/20)->Q
10fPart(Q/200)->C // 200/20=10
iPart(Q/200)->Q
5fPart(Q/1000)->B // 1000/200=5
iPart(Q/1000)->A //ce quotient sera identique au prochain reste puisqu'on est à la fin
reste systématique (mais coeffs multiples !!! sinon marche pas)
1000A+200B+20C+D->X
20fPart(X/10)->D
10fPart((X-D)/100)->C
5fPart((X-D-C20)/1000)->B
(X-D-C20-B200)/1000->A // pas un reste, c'est pour faire plus simple
Dernière édition par Linkakro le Dim 17 Nov 2013 - 17:23, édité 1 fois
Linkakro- ----------------------
- Messages : 533
Points Concours : 55
Productivité : 31
Date d'inscription : 30/07/2013
Localisation : origine région centre, puis perpignan
Calculatrice(s) :- TI-82 Stats.fr
. :
Re: Sauvegarder des données
Merci pour tes remarques, je me penche dessus dès que j'ai le temps.
m@thieu41- ----------------------
- Messages : 939
Points Concours : 65
Productivité : 47
Date d'inscription : 02/06/2013
Localisation : Nice, France
Calculatrice(s) :- TI-82 Stats.fr
. :
Sujets similaires
» Record du monde de compression de données :P
» [Graphismes] Dessinez avec une base de données
» Proposez vos cours pour la base de données du site !
» [Graphismes] Dessinez avec une base de données
» Proposez vos cours pour la base de données du site !
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
Dim 16 Oct 2022 - 21:11 par Wistaro
» Bonne année 2018!
Ven 2 Nov 2018 - 19:42 par Ti64CLi++
» Lancement du TI-Concours 2017 !
Sam 20 Mai 2017 - 0:27 par Paulo1026
» Chaînes Youtube des membres
Ven 19 Mai 2017 - 22:41 par Wistaro
» cacul du taux d'intêret
Ven 24 Mar 2017 - 21:50 par m@thieu41
» [Projet] Un mario by tout82
Dim 29 Jan 2017 - 14:09 par Wistaro
» Cherche documentation assembleur TI82stat
Mer 25 Jan 2017 - 12:29 par Ti64CLi++
» Probleme Ti-82 Stats fr
Jeu 12 Jan 2017 - 13:56 par Ti64CLi++
» ROM 82 stats.fr
Jeu 15 Déc 2016 - 10:24 par Ti64CLi++