Rechercher
 
 

Résultats par :
 


Rechercher Recherche avancée

Connexion

Récupérer mon mot de passe

Chatbox externe


Derniers sujets
» [JEU] Mon voisin du dessous
Dim 3 Sep 2017 - 19:50 par Clément.7

» 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++

» flappy bird
Jeu 15 Déc 2016 - 10:23 par Ti64CLi++

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
Ti64CLi++
 
Clément.7
 


Sauvegarder des données

Voir le sujet précédent Voir le sujet suivant Aller en bas

Sauvegarder des données

Message par m@thieu41 le Lun 29 Juil 2013 - 17:26

Sauvegarder des données, savoir si le programme a déjà été lancé, compresser des informations, tout est à votre portée! Wink

Bonjour à tous ! Very Happy 

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. Smile 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 ! Cool

Pour commencer, vous avez besoin de connaître les listes personnalisées, puisqu'on va devoir les utiliser Wink. 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 ! cheers
Tant que vous ne modifiez/supprimez pas la liste personnalisée, vos informations sont en (relative) sécurité Wink


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 Razz 
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 Wink.

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é ! Wink

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
Il est plus judicieux de faire:
Code:
{1,1,10,7,5->SNAKE
Comme vous pouvez le voir c'est bien plus optimisé Wink

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
On a donc :
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é ;
Vous pouvez même, en restaurant, le faire dans une seule variable, et tester sa partie entière/décimale pour savoir si le joueur possède ou non des pouvoirs!


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
Pas très compliqué en fait Smile .


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 Wink)
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 Wink.
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 Razz): 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 ! Bien Joué 

Si vous avez des questions, suggestions, conseils, n'hésitez pas Wink

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

__________________________________________________________________________
ZSNAKE Mon premier (et unique) jeu en ASM:
Un Snake 2 joueurs (2caltos)
-> Je travaille sur une version plus stable du jeu, je poste dès que possible.
avatar
m@thieu41
----------------------
----------------------

Messages : 934
Points Concours : 65
Productivité : 47
Date d'inscription : 02/06/2013
Localisation : Nice, France
Calculatrice(s) :
  • TI-82 Stats.fr

. : TI-82 Stats.fr

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par Linkakro le Mer 31 Juil 2013 - 3:24

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.
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
Je ne pense pas qu'on puisse compresser des données de signe opposé, mais si vous le faites vous devrez ne pas confondre partEnt et ent qui sont mal traduites de int et iPart.

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. (tester un terme non-nul, que ce soit une donnée ou une information réservée)
avatar
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

. : TI-82 Stats.fr

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par m@thieu41 le Mer 31 Juil 2013 - 10:05

Merci pour tes remarques, je vais modifier 2-3 truc Wink

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.

__________________________________________________________________________
ZSNAKE Mon premier (et unique) jeu en ASM:
Un Snake 2 joueurs (2caltos)
-> Je travaille sur une version plus stable du jeu, je poste dès que possible.
avatar
m@thieu41
----------------------
----------------------

Messages : 934
Points Concours : 65
Productivité : 47
Date d'inscription : 02/06/2013
Localisation : Nice, France
Calculatrice(s) :
  • TI-82 Stats.fr

. : TI-82 Stats.fr

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par blg_flg le Mer 7 Aoû 2013 - 19:04

Sujet déplacé dans la section article, s'agissant plus d'un tutoriel.

__________________________________________________________________________




A bove ante, ab asino retro, a moderatoro undique caveto.

Invité, tu désires la liberté ? Fais donc un petit tour sur TI-Free World !

Spoiler:
avatar
blg_flg
Connaisseur
Connaisseur

Messages : 249
Points Concours : 45
Productivité : 6
Date d'inscription : 04/06/2013
Localisation : Pantruche
Calculatrice(s) :
  • TI-82 Stats.fr

. : TI-82 Stats.fr

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par Linkakro le Dim 8 Sep 2013 - 20:54

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
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 Wink)
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 Wink.
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
Pour moi des détails importants manquent pour comprendre. Et je corrige une erreur et une chose pas judicieuse.

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
rassemblé différemment les actions, pour éviter la complication de l'extraction et distinguer domaine/compression
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.
développé plus en détail, il faudrait commencer par ça puis éventuellement optimiser comme c'était fait avant par m@thieu41 (excepté la complication).
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

__________________________________________________________________________
Vétéran du TI-Basic Zilog80. Ti82statfr sur Tout82 depuis 2009 et ti84pocketfr depuis noël 2012. Ti83plusfrUSB (été 2014, concours tiplanet suite du geek). Bidouille un peu d'assembleur Z80.
Incappable de gérer le temps et manque de tact, plutôt serviable.
Je prend les commandes de programme. Je suis motivé par les maths et la physique tant que ce n'est pas une simple copie d'antisèche.
Vous pouvez trouver une grande partie de mes données hébergées dans mon mediafire. Le ZIP et la liste sont périmées depuis longtemps.
coucou Invité What a Face
avatar
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

. : TI-82 Stats.fr

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par m@thieu41 le Dim 8 Sep 2013 - 21:48

Merci pour tes remarques, je me penche dessus dès que j'ai le temps.

__________________________________________________________________________
ZSNAKE Mon premier (et unique) jeu en ASM:
Un Snake 2 joueurs (2caltos)
-> Je travaille sur une version plus stable du jeu, je poste dès que possible.
avatar
m@thieu41
----------------------
----------------------

Messages : 934
Points Concours : 65
Productivité : 47
Date d'inscription : 02/06/2013
Localisation : Nice, France
Calculatrice(s) :
  • TI-82 Stats.fr

. : TI-82 Stats.fr

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par ashtrail le Ven 27 Sep 2013 - 23:58

Tuto très instructif. +1!

__________________________________________________________________________
Mes programmes :
-JEUX : Le TAPTAUPE, Le MINSTEP, Un Plus-Moins
-MATHS : Regroupement n°1, Regroupement n°2, tout sur les pourcentages
-AUTRE : Le programme qui jauge les prénoms
avatar
ashtrail
Connaisseur
Connaisseur

Messages : 248
Points Concours : 21
Productivité : 21
Date d'inscription : 18/06/2013
Localisation : Paris
Calculatrice(s) :
  • TI-82 Stats.fr

. : TI-82 Stats.fr

Voir le profil de l'utilisateur http://ti-freeworld.fr1.co/

Revenir en haut Aller en bas

Re: Sauvegarder des données

Message par Contenu sponsorisé


Contenu sponsorisé


Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum