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

Embarqué Discussion :

caster/tronquer float en int


Sujet :

Embarqué

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Par défaut caster/tronquer float en int
    Bonjour à tous,

    Je dois developper deux petites fonctions en C compilé par diab pour aller sur un MPC555.

    Mise en situation:
    Le logiciel sur lequel je travail ecrit des blocks (ie 0 to 5023) dans une memoire et doit garder une trace des blocks ecrit. A chaque fois qu'un block est ecrit, on appel une fonction qui s'occupe de marquer ces blocks comme ecrit. Il faut aussi etre capable de retourner, à l'aide d'une autre fonction, si un block passé en parametre est ecrit.

    Premier choix on crée un tableau, contenant des variable de 32 bits, en supposant que ca ameliore par rapport a des variables de 8, 16 ou 64 bits
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define size (5024u)
    static unsigned int history[size/32u]
    On a donc cette fonction prenant forcement un unsigned short en entrée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void setblock(unsigned short block_id)
    {
    unsigned int mask;
    unsigned int index;
    
    //on cree notre mask pour aller ecrire dans le tableau
    mask =  (unsigned int)(1u<<(block_id%32u));
    //on determine a quelle position ecrire
    index = (unsigned int)(block_id/32u);
    //et on vient updater le tableau
    history[index] |= mask;
    }
    Premiere question, etes vous d'accord avec ce code d'un point de vue des performance ?
    Aussi je ne veux laisser aucun cast implicite.

    Deuxieme question, d'apres ce que je sais, la version de diab que j'utilise ne fera pas le castage du float comme je l'attend.
    int i = (int)(1.7) --> 2 et non 1.

    Je voudrais donc contourner ce probleme, mais de facon a ce que le resultat soit comme attendu et ce, pour difference type de compilateur.
    ie: sur gcc int i = (int)(1.7) --> 1.

    Auriez vous une suggestion ?

    Merci beaucoup pour votre aide et vos suggestions

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 496
    Billets dans le blog
    1
    Par défaut
    J'ai du mal à bien cerner ta fonction set_block, je vais donc partir du principe que tu sais ce que tu fais

    Quelques remarques :

    1) La définition du tableau d'historique : c'est que tu vas lister les numéros des blocs que tu as déjà écrit ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define size (5024u)
    static unsigned int history[size/32u]
    Avec ça, tu ne crées pas un tableau d'éléments chacun codé sur 32 bits. Tu crées un tableau de 5024/32=157 unsigned int. Quelle est la taille d'un unsigned int avec ton compilateur ? 16 ou 32 ?

    2) Sur la fonction set_block : avant de penser au cast, il faut voir que diviser un entier par un autre ne donne pas un float mais un entier. Avec Gcc sour Ubuntu, le code suivant me code 0 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main(void)
    {
        printf("%d",2/16);
        return 0;
    }
    J'ai aussi du mal à comprendre cette fonction. Tu généres ce que tu dois écrire dans le bloc d'historique à partir de l'identifiant du bloc ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Par défaut
    Tout d'abord, merci pour ta reponse.

    Je but de la fonction est le suivant : à chaque ecriture du logiciel dans une memoire externe (la place à ecrire est identifié par un identifiant de block), on veut pouvoir garder une trace de l'identifiant de block ecrit (l'identifiant etant sont numero).

    Plutot que de faire une table de boolean de taille [0-5023], je me suis dit que vu de l'architecture de la cible materiel était de 32 bits, il valait mieux gerer une table comme decrite dans mon precedent post.

    Citation Envoyé par Bktero Voir le message
    Quelle est la taille d'un unsigned int avec ton compilateur ? 16 ou 32 ?
    C'est bien 32 bits
    D'ou ma premiere question, est ce une choix judicieux ?

    Aussi, si jamais je declare le mask en float, le resultat de la division de deux entiers sera elle aussi forcement un entier ?

    Prenons une exemple:
    Si j'envoi une requete d'ecriture sur le block 7, je veux donc ecrire à l'index 0 de mon table le mask suivant : 0000 0000 0000 0000 0000 0000 1000 0000
    Si j'envoi une requet d'ecriture au block 60, je veux ecrire à l'index 1 de mon tableau le mask suivant : 0001 0000 0000 0000 0000 0000 0000 0000
    Le probleme vient du fait que, celon le compilateur (et j'espere ne pas me tromper)
    -Sur GCC : 60/32 = 1 : comportement comme attendu
    -Sur Diab : 60/32 = 0 : comportement troublant

    Je suis donc à la recherche d'une solution pour corriger cette situation et qui serait portable celon le compilateur.
    Si cette solution est trop couteuse, en temps d'execution, je soustrairai simplement 32 à mon block id pour contourne le probleme.

    Merci pour les retours

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 496
    Billets dans le blog
    1
    Par défaut
    il valait mieux gerer une table comme decrite dans mon precedent post.
    Désolé mais tes exemples ne m'ont pas aidé à comprendre le principe de cette table. Pendant un instant, j'ai pensé que tu voulais faire un champ de bits (1 par bloc) et mettre à un le bit correspondant à chacun des blocs (c'est pas mal comme idée d'ailleurs). A moins que tu ne te sois planté dans tes exemples ^^

    Je présume que ton souhait est d'économiser de la mémoire plutôt que de gagner en performances (ce qui, pour moi, correspond à un gain de vitesse d’exécution). En effet, je ne pense pas que tu puisses faire plus rapide qu'accéder à un tableau avec une instruction telle que history[index];, sans faire d'autres calculs.

    Aussi, si jamais je declare le mask en float, le resultat de la division de deux entiers sera elle aussi forcement un entier ?
    Si tu déclares le masque en flottant, tu risques de ne pas pouvoir l'appliquer après ! Il doit rester de type int. Il faut par contre changer la division. Il faut que tu regardes la documentation de ton compilateur pour savoir comment se fait la division et comment sont faites les promotions de types. J'ai constaté il y a quelques jours dans la documentation du compilateur C18 pour PIC qu'il y avait des différences avec la norme. Tu dois avoir un point similaire avec ton compilateur, ce qui explique la différence de comportement avec GCC. Soyons fous, tu as peut-être un flag de compilation particulier pour changer le comportement.

    Dans Gcc, si tu veux avoir un résultat en flottant, il faut que l'un des opérandes soit de type flottant. Après, le cast vers un type int pourra aussi changer. La solution pourrait être d'utiliser une fonction d'arrondi / troncature dont tu maitrises le comportement.

    Enfin, dernière remarque sur la portabilité : tu es totalement dépendant de la taille du int. Tu devras faire des redéfinitions de types si tu changes d'architecture. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef int32 int; // sur une machine 32 bits
    typedef int32 short int; // sur une machine 64 bits
    Si tu arrives sur des architectures où tu n'as pas d'objets sur 32 bits (je pense à un µC 8 bits), tu auras un problème : encore une autre solution : faire un tableau de char et non d'int.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Pendant un instant, j'ai pensé que tu voulais faire un champ de bits (1 par bloc) et mettre à un le bit correspondant à chacun des blocs (c'est pas mal comme idée d'ailleurs). A moins que tu ne te sois planté dans tes exemples ^^
    C'est mon idée, désolé de t'avoir perdu avec mes exemples.

    Citation Envoyé par Bktero Voir le message
    Je présume que ton souhait est d'économiser de la mémoire plutôt que de gagner en performances (ce qui, pour moi, correspond à un gain de vitesse d’exécution).
    Je cherche à avoir un temps d’exécution le plus faible possible.

    Concernant la division par 32, j'ai pensé un peu plus au niveau bit, et il me semble que faire un bitshift vers la droite de 5 me donnerai le comportement attendu et serait bien plus efficace.


    Citation Envoyé par Bktero Voir le message
    Enfin, dernière remarque sur la portabilité : tu es totalement dépendant de la taille du int. Tu devras faire des redéfinitions de types si tu changes d'architecture. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef int32 int; // sur une machine 32 bits
    typedef int32 short int; // sur une machine 64 bits
    C'est déja fait mais je ne voulait pas surcharger le post.

    Citation Envoyé par Bktero Voir le message
    Si tu arrives sur des architectures où tu n'as pas d'objets sur 32 bits (je pense à un µC 8 bits), tu auras un problème : encore une autre solution : faire un tableau de char et non d'int.
    Donc il serait plus judicieux d'utiliser une table contenant les unsigned int définis sur 8 bits.


    En tout cas, merci pour tes reponse elles m'ont aidé à y voir plus claire.

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 496
    Billets dans le blog
    1
    Par défaut
    C'est mon idée, désolé de t'avoir perdu avec mes exemples.
    Pas de soucis

    C'est déja fait mais je ne voulait pas surcharger le post.
    Je m'en doutais un peu.

    Je cherche à avoir un temps d’exécution le plus faible possible.
    Si tu souhaites avoir la meilleure vitesse, il faut faire un tableau de 5024 éléments à mon avis. Bon, tu vas tuer ta mémoire même si tu utilises des char

    Bien vue la division par 32 en faisant des décalages. Ca devrait être plus rapide et surtout le résultat est plus certain. Le cast devient inutile de plus.

    En tout cas, merci pour tes reponse elles m'ont aidé à y voir plus claire.
    De rien !

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

Discussions similaires

  1. caster un TObject en int
    Par Art19 dans le forum Delphi
    Réponses: 2
    Dernier message: 02/04/2007, 19h02
  2. cast float vers int
    Par planeur2007 dans le forum C
    Réponses: 5
    Dernier message: 13/03/2007, 18h39
  3. float to int
    Par Despak dans le forum C++
    Réponses: 8
    Dernier message: 23/02/2007, 13h07
  4. probleme de conversion float en int
    Par murreya dans le forum C++
    Réponses: 2
    Dernier message: 17/12/2005, 15h27
  5. Conversion float vers int
    Par vargasvan dans le forum C
    Réponses: 2
    Dernier message: 05/10/2005, 17h29

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