IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Rebouclement de compteur


Sujet :

Langage Delphi

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2005
    Messages : 32
    Points : 27
    Points
    27
    Par défaut Rebouclement de compteur
    Bonjour à tous.
    Je cherche de l'aide sur les compteurs. J'ai une appli qui interroge sur tache un compteur (integer) dans une FPGA(ça c'est pour l'anecdote car ça pourrait être n'importe quel compteur qui ne fait que de s'incrémenter) pour en sortir un delta compteur. J'aimerais traiter le passage par zero entre 2 appels.
    Il me semble qu'il est possible de traiter ce passage en transtypant le résultat en integer ou qqchose comme ça.
    Mon problème c'est que je ne sait plus comment faire et surtout que j'aimerais comprendre comment ça fonctionne.

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    1 085
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2002
    Messages : 1 085
    Points : 886
    Points
    886
    Par défaut
    Hum, un ptit dessin serait pas de refus pcq là, ce n'est pas trop clair

    Merci

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    bonjour,

    l'aide de delphi nous donne:

    Type Etendue Format
    Shortint -128..127 8 bits signé
    Smallint -32768..32767 16 bits signé
    Longint -2147483648..2147483647 32 bits signé
    Int64 -2^63..2^63-1 64 bits signé
    Byte 0..255 8 bits non signé
    Word 0..65535 16 bits non signé
    Longword 0..4294967295 32 bits non signé


    si vous mettez un integer à 0 et que vous l'incrémenter 2147483647 fois, vous optiendrez le maximume de la valeur d'un integer. si vous l'incrémentez encore une fois vous aurrez le minimume de la valeur (-2147483648) puis vous remonterez ver zéro.

    Cela est pour les fonction de base des entiers.

    Si vous voulez des traitements spéciaux déclencher par un changment de compteur, ou savoir quand vous incrementer ou intéroger un compteur, vous pouver utiliser une property.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
    private
      FCompteur: Integer;
      procedure SetCompteur(Value: Integer);
      function GetCompteur: Integer;
    public
      property Compteur read GetCompteur write set compteur;
    implementation
     
    // dans le onformcreate de votre form
    FCompteur := 0;
     
    function TMyform.GetCompteur: Integer;
    begin
      result := FCompteur;
    // Eventuellment un traitement en plus
    end;
     
    procedure TMyform.SetCompteur(Value: Integer);
    begin
      FCompteur := Value;
    // Eventuellment un traitement en plus, ou des test etc..
    end;
    Avec cette property si vous faite
    "X := Compteur;" vous appelerez en faite la function GetCompteur.
    si vous faite "Compteur := X;" vous applerez SetCompteur.
    Vous pouvez donc mettre un "Flag" indiquant que vous etes en train de changer le compteur et faisant attendre un utilisateur qui interrogerai compteur. par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function  Myform.GetCompteur: Integer;
    begin
      while FCompteurIsInReset do begin
        Application.ProcessMessages;
      end;
      Result := Fcompteur;
    end;

  4. #4
    Membre actif
    Profil pro
    ----
    Inscrit en
    Mai 2004
    Messages
    185
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ----

    Informations forums :
    Inscription : Mai 2004
    Messages : 185
    Points : 245
    Points
    245
    Par défaut
    Delphi ne fait de test d'overflow ?
    Si le problème et pour la passage a zero... essay d'utiliser les modulo
    De toutes les choses que j'ai perdue,
    Celle qui me manque le plus...
    c'est mon esprit !

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2005
    Messages : 32
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par portu
    Hum, un ptit dessin serait pas de refus pcq là, ce n'est pas trop clair

    Merci
    Je vais tenter d'être plus clair, d'autant que j'ai retrouvé la fonction aujourd'hui.
    A chaque passage dans ma tache j'interroge une variable qu'on appellera FCompteur. Ce qui m'intéresse c'est de savoir de combien s'est incrémenté le compteur entre 2 appels.
    Donc je vais stocker le comteur au premier passage dans un FCompteurold (A). Au second passage je stocke le compteur dans un FCompteurNew (B).
    Pour connaître la différence, je suis sensé pouvoir faire une soustraction. Mais comme je ne connais pas le contenu de mon compteur, il se peut que ce dernier soit passé par sa taille maximum (4294967295) et qu'il recommence donc à 0, ce qui donnera une valeur négative.

    J'ai retrouvé la fonction qui permet de gérer ceci, mais j'ai besoin d'une petite explication.

    La fonction est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function Sub2CardinalToCardinal(A,B : Cardinal):cardinal;
    begin
       asm
          sub eax, edx; {permet une soustraction en supprimant les contrôles je crois}
       end;
    end; //Sub2CardinalToCardinal
    Si j'obtiens une valeur négative dans la partie assembleur, c'est que je suis passé par 0 avec mon compteur.
    Comme j'ai déclaré le retour de ma fonction en cardinal, je ne peut obtenir qu'un nombre positif, d'où un transtypage de nombre négatif en cardinal.
    Et c'est là que je ne comprends pas comment ce transtypage me permet de trouver la différence correcte entre mes 2 appels comme si le compteur avait continué à incrémenté et n'avait pas redémarré à 0 après 4294967295 (valeur max d'un cardinal).
    Y'a surement une histoire de bit de signe mais je ne suis pas fortiche là-dedans.

    Merci pour votre aide et désolé d'être un peut confu.

  6. #6
    Membre actif
    Profil pro
    ----
    Inscrit en
    Mai 2004
    Messages
    185
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ----

    Informations forums :
    Inscription : Mai 2004
    Messages : 185
    Points : 245
    Points
    245
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function Sub2CardinalToCardinal(A,B : Cardinal):cardinal;
    begin
       asm
          sub eax, edx; {permet une soustraction en supprimant les contrôles je crois}
       end;
    end; //Sub2CardinalToCardinal
    ce code ne fait qu'une bête soustraction qui correspondrat en delphi a eax = eax - edx.
    Effectivement si edx > eax, alors eax est négatif... mais en immaginant que edx = int.max et eax = 0. Il n'y a que 1 d'écart et tu te retrouve avec -int.max en résultat (en gros...). Le transtypage t'aideras pas plus que ça !
    si eax > edx, pas de problème.

    Essay plutôt de détecter le passage à 0.
    Ou alors, tu peut essayer la dernière métode, masi si eax <0 alors eax = int.max - eax... a +/- 1 prés ça doit être ça

    Ou encore tu incrémente deux variable. Une qui est effectivement ton compteur, et une autre que tu remet a zeros quand tu l'a vérifier... ça ne pouras pas indiquer s'il y'a eu un double bouclage, et ça demande deux fois plus de cicle (au lieu d'un il t'en faut deux... c'est pas la mort )
    De toutes les choses que j'ai perdue,
    Celle qui me manque le plus...
    c'est mon esprit !

  7. #7
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 770
    Points
    2 770
    Par défaut
    Citation Envoyé par /dev/null
    Ou encore tu incrémente deux variable. Une qui est effectivement ton compteur, et une autre que tu remet a zeros quand tu l'a vérifier... ça ne pouras pas indiquer s'il y'a eu un double bouclage, et ça demande deux fois plus de cicle (au lieu d'un il t'en faut deux... c'est pas la mort )
    bon méthode
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    bonjour

    Peut longword peut il être plus pratique qu'un integer pour votre compteur ?
    (Longword 0..4294967295 32 bits non signé)

    Ensuite si vous utiliser une procedure pour incrementer votre compteur, vous pouvez avoir le nombre de cicle.




    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    private 
      FCompteur: LongWord;
      FCycle:LongWord;
    public
      procedure IncCompteur(Value: word);
    implementation;
     
    procedure TMyForm.IncCompteur(Value: word);
    var
      ASave: Longword;
    begin
      ASave := FCompteur;
     FCompteur := FCompteur + Value;
     if (FCompteur < ASave) or (Value = high(Longword)) then
      FCycle := Fcycle + 1;
    // Si je boucle (en passant par 0) ou si value = la valeur max de longWord, je passe au cycle suivant.
    end;
    Ensuite vous comparez sur FCycle et Fcompteur plutôt que sur FCOmpteur pour trouvez le nombre d'imlementation entre 2 apelle.

    Autre solution.
    Ajouter une valeur FImplementation (Longword), et implementer la de la même valeur que fCompteur dans la procedure IncCompteur.

    Il vous suffit de lire la valeur pour savoir le nombre d'implementation depuis que la valeur à été mise à zéro. (si un longword est tros court,il faut la aussi gérer un nombre de cycle).

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2005
    Messages : 32
    Points : 27
    Points
    27
    Par défaut
    A force de chercher sur différents sites j'ai trouvé l'explication que je cherchais, à savoir pourquoi la fonction que j'ai décrite précédemment fonctionne.
    Pour ceux que ca intéresse voici l'explication :

    Reprenons la fonction mais avec des types plus légers pour éviter de gros calculs, donc par exemple des byte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Function SubAToB(A,B : Byte) : Byte;
    begin
      asm
        sub eax, ebx;
      end;
    end;
    Je dois passer par l'assembleur pour éviter une erreur lors de l'execution si le resultat est negatif.

    Prenons un exemple, admettons que mon compteur était au premier appel à 243.
    Lors du deuxième appel, comme celui-ci n'a fait qu'incrémenter et est passé par zéro 1 seule fois, il est à 15.

    Pour savoir de combien s'est incrémenté mon compteur, je vais soustraire ces 2 valeurs (a vue d'oeil on voit que le résultat devrait être 256+15-243= 28 ).

    Voici comment s'execute la soustraction A-B, en passant par la méthode des compléments à 2:
    A = 15, B = 243, à calculer en binaire
    A (sur 8 bits car type byte): 00001111
    B (sur bits aussi) : 11110011
    Au lieu de soustraire B, on va additionner son complément à 2 :
    déterminer le complément à 2 en 2 phases
    complément à 1 en inversant tous les bits de B (sur 8bits toujours car byte): 00001100
    complément à 2 en ajoutant 1 : 00001101

    Il suffit d'additionner en base 2 les deux nombres et de tronquer à 8 bits si nécessaire : 00001111 + 00001101 = 00011100
    Ce qui donne en décimal : 28

    Et voila, j'ai pu de manière simple connaître de combien s'était incrémenté mon compteur en tenant compte de tous les cas, même le passage par zéro.

    Merci de votre aide et j'espère que ça pourra aider une autre personne.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [FLASH MX2004] Compteur progressif 0 à 95%
    Par DJeys dans le forum Flash
    Réponses: 5
    Dernier message: 21/07/2004, 14h58
  2. [XSL FO] Compteur a partir de 2
    Par Hugo001 dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 30/06/2004, 11h39
  3. [PB CONCEPTUEL] avec compteur/trigger
    Par kase74 dans le forum SQL
    Réponses: 6
    Dernier message: 25/03/2004, 11h02
  4. Remise à 0 d'un compteur automatique
    Par missllyss dans le forum SQL
    Réponses: 4
    Dernier message: 15/12/2003, 16h46
  5. Migration Access > SQL Server (suite) : Compteur
    Par LadyArwen dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 06/03/2003, 14h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo