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

C++ Discussion :

Division interactive avec gestion des types


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur géomaticien
    Inscrit en
    Juillet 2015
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur géomaticien

    Informations forums :
    Inscription : Juillet 2015
    Messages : 34
    Points : 24
    Points
    24
    Par défaut Division interactive avec gestion des types
    Bonjour à tous et bonne année !

    Je cherche à trouver le mécanisme en C++ qui permet de gérer dynamiquement les types lors d'une division en fonction des nombres entrés par l'utilisateur.
    La division que je cherche à implémenter doit avoir les règles suivantes (le type des opérandes et du résultat est noté entre crochets) :
    • a [float] divisé par b [float] renvoie a/b [float]
    • a [int] divisé par b [float] renvoie a/b [float]
    • a [float] divisé par b [int] renvoie a/b [float]
    • Le cas difficile : a [int] divisé par b [int] renvoie la division entière a/b [int] ssi a % b = 0, sinon renvoie la division flottante (float)a/b [float]


    Exemple d'exécution (le code tapé par l'utilisateur est rouge) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >> Entrez le nombre initial : 4
    >> Entrez le diviseur : 2
    Résultat : 2 [int]
    >> Entrez le diviseur : 1
    Résultat : 2 [int]
    >> Entrez le diviseur : 2
    Résultat : 0.5 [float]
    >> Entrez le diviseur : 3
    Résultat : 0.16666666 [float]
    
    etc.
    Je n'arrive pas à écrire la boucle qui permette de se "souvenir" au moment de l'exécution du type du résultat d'une itéartion à l'autre, et de renvoyer le type ad hoc en fonction du type et de la valeur des arguments.
    Ma première idée était de surcharger quatre fois une fonction div pour int et float, mais ce n'est pas possible car en C++ il n'est pas possible de décider d'un type de retour en fonction de la valeur des arguments à l’exécution...

    Des idées ?

    Jean

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Je pense que c'est impossible en C++ : tu peux pas déduire un type à l'exécution (hors héritage / polymorphisme).

    Si tu divises des constantes, les templates peuvent aider :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <class T, class U>
    auto div(T lhs, U rhs) -> decltype(lhs / rhs) {
       return lhs / rhs;
    }
     
    auto a = div(1, 1); // int
    auto b = div(1.f, 1); // float
    auto c = div(1, 1.f); // float
    auto d = div(1.f, 1.f); // float
    auto e = div(1., 1); // double

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par jportemer Voir le message
    • a [float] divisé par b [float] renvoie a/b [float]
    • a [int] divisé par b [float] renvoie a/b [float]
    • a [float] divisé par b [int] renvoie a/b [float]
    • Le cas difficile : a [int] divisé par b [int] renvoie la division entière a/b [int] ssi a % b = 0, sinon renvoie la division flottante (float)a/b [float]
    Tout ceci n'est rien d'autre qu'une division de flottants. Ton "cas difficile" n'a rien non plus de particulier. Si a%b = 0 alors la division renverra un entier par définition..
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Ingénieur géomaticien
    Inscrit en
    Juillet 2015
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur géomaticien

    Informations forums :
    Inscription : Juillet 2015
    Messages : 34
    Points : 24
    Points
    24
    Par défaut
    Merci à vous 2 pour vos réponses.

    Citation Envoyé par Bousk Voir le message
    Tout ceci n'est rien d'autre qu'une division de flottants. Ton "cas difficile" n'a rien non plus de particulier. Si a%b = 0 alors la division renverra un entier par définition..
    Je suis tout à fait d'accord avec toi, c'est la division C++ "classique". Mais justement, la division interactive que je cherche a faire n'a pas les mêmes règles que cette définition classique, et il est impossible de la définir avec une fonction C++ (à cause du type de retour variable) :
    Si a % b == 0, je veux un int en résultat, sinon, je veux un float.

    Autre exemple : une racine carrée prolongée dans l'ensemble des float négatifs
    Si l'argument a [int ou float] est positif, je renvoie std::sqrt(a) [float]
    Si l'argument a [int ou float] est strictement négatif, je renvoie std::complex<float>(0,1) * std::sqrt(-a) [std::complex<float>]

    Je comprends bien que ce n'est pas possible en mode compilé car tous les types doivent être connus à la compilation. Mais en mode interprété il doit bien y avoir un moyen non ?

    En Python, si vous connaissez, le type d'une expression peut être déterminé par sa valeur (donc à fortiori il est possible de définir des fonction avec des types de retour variables, même si la plupart des primitives du langage ont un type de retour fixé), et pourtant l'interpréteur CPython est écrit en C. De même pour Ruby, Matlab, J...

    En Python 3.4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    >>> def div(a, b): # Le type de retour de la fonction est déterminé par sa valeur
    ...     return a//b if a%b == 0 else a/b # // est la division entière, / est la division flottante
    ...
    >>> type(div(4,2)), div(4,2)
    (<class 'int'>, 2)
     
    >>> type(div(4,3)), div(4,3)
    (<class 'float'>, 1.33333333333333333333)

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par jportemer Voir le message
    le type d'une expression peut être déterminé par sa valeur
    Justement, si tu fais un parser de nombre avec au moins la gestion du signe et flottant/ entier, tu pourras déterminer à l'exécution le type de tes nombres et faire ce que tu veux [avec sûrement un switch]

  6. #6
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par jportemer Voir le message
    Autre exemple : une racine carrée prolongée dans l'ensemble des float négatifs
    Si l'argument a [int ou float] est positif, je renvoie std::sqrt(a) [float]
    Si l'argument a [int ou float] est strictement négatif, je renvoie std::complex<float>(0,1) * std::sqrt(-a) [std::complex<float>]
    Tu peux renvoyer des complex tout le temps.

    'x' et 'x + 0i' c'est équivalent (mathématiquement), si tu as besoin de ça travaille avec des complex.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par jportemer Voir le message
    Je suis tout à fait d'accord avec toi, c'est la division C++ "classique". Mais justement, la division interactive que je cherche a faire n'a pas les mêmes règles que cette définition classique, et il est impossible de la définir avec une fonction C++ (à cause du type de retour variable) :
    Si a % b == 0, je veux un int en résultat, sinon, je veux un float.
    - en ne travaillant qu'avec des float ça fait exactement ce que tu présentes dans le premier post
    - 2 est autant un float qu'un int et à l'affichage dans std::cout il sort bel et bien 2
    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
    #include <iostream>
     
    int main()
    {
    	float a, b;
    	std::cout << "a="; std::cin >> a;
    	std::cout << "b="; std::cin >> b;
    	float r = a / b;
    	std::cout << "a/b=" << r << std::endl;
     
    	if (static_cast<int>(r) == r)
    	{
    		std::cout << r << " est entier";
    	}
    	else
    	{
    		std::cout << r << " n'est pas entier";
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=4
    b=2
    a/b=2
    2 est entier
    Et la console affiche bien un 2. Le float caché derrière l'utilisateur s'en moque.
    Et tu ne devrais pas t'en soucier non plus. Et si tu veux absolument manipuler un int, tu cast.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=4
    b=5
    a/b=0.8
    0.8 n'est pas entier
    Citation Envoyé par jportemer Voir le message
    Autre exemple : une racine carrée prolongée dans l'ensemble des float négatifs
    Si l'argument a [int ou float] est positif, je renvoie std::sqrt(a) [float]
    Si l'argument a [int ou float] est strictement négatif, je renvoie std::complex<float>(0,1) * std::sqrt(-a) [std::complex<float>]
    On sort du cadre de la simple division..
    - énonce le problème entier pour y apporter une solution, si tu arrives à chaque fois qu'on te propose une solution fonctionnelle avec un cas de plus à gérer ça va pas marcher..
    - ce problème n'a rien à voir avec une division et est bien plus spécifique mais pas plus dur à résoudre : des complexes partout; libre à toi de ne pas afficher la partie imaginaire si elle est nulle, ou la partie réelle
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Ingénieur géomaticien
    Inscrit en
    Juillet 2015
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur géomaticien

    Informations forums :
    Inscription : Juillet 2015
    Messages : 34
    Points : 24
    Points
    24
    Par défaut
    OK.
    Merci à tous je vais rester sur des floats et ne distinguer qu'à l'affichage, ça suffira amplement.
    Je passe le post en résolu.

    Jean

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 24/04/2012, 13h53
  2. peupler un treeview avec gestion des noeuds
    Par Alabama-song dans le forum ASP.NET
    Réponses: 3
    Dernier message: 25/01/2008, 20h35
  3. Réponses: 8
    Dernier message: 15/10/2006, 18h45
  4. Gestion des types de variables en Assembleur
    Par AsmCode dans le forum Assembleur
    Réponses: 13
    Dernier message: 17/10/2005, 20h34
  5. GEstion des types! Besoin d'aide il me manque quelques trucs
    Par popogendarme dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 03/02/2005, 18h56

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