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 :

Résolution d'integrales avec variable variant dans la boucle


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut Résolution d'integrales avec variable variant dans la boucle
    Bonjour,

    Je souhaite créer un programme pour résoudre des intégrales afin de tracer au final une courbe. Pour l'instant je me concentre sur la premiere integral qui se résume à l'estimation de cette somme:
    Nom : Capture.PNG
Affichages : 278
Taille : 14,3 Ko

    Mon soucis est que ma donné psi évolue selon n mais aussi en fonction des valeurs qu'elle a pris pour n-1. Je suis un peu perdu en C pour savoir comment lui dire d'utilisé les valeurs calculées avant pour faire la valeur suivante. Dois-je passé par un tableau? peut-il me le remplir au fur et a mesure des données?
    J'ai tenté d’écrire un programme le plus simple possible (en estimant toutes les constantes), mais pour l'instant je ne peux pas lancer l'application, car c'est certainement beaucoup trop simple....:

    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
    25
    26
    27
    28
    29
    30
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define pi 3.1416
    #define R 8.144621
    #define T 298.15
    #define F 96485
    #define alpha 1
     
    float k1,to,Eimp,dj;
    int j, n;
     
    int main()
    {
        k1=10.0;to=5.5;Eimp=0.6;dj=0.001;n=500;
        psi=0.0;
        dt=1/n;
        for(i=1;i<=n;i=i++); 
        { 
            for(j=i-1;i<n;j+=dj);
            {
                psi+=(1+1.33*1/(sqrt(pi))*sqrt(dt)*(psi(j)*pow(n-j+1,(3/2))+2*pow(n-j,(3/2))+pow(n-j-1,(3/2)))*dj)/(exp((-alpha*F/(R*T)))+1.33*(1/sqrt(pi))*sqrt(dt));
        }
     
        printf("l'integral de psi =%3.3f",psi);
        return 0;
        }
     
     
    }
    Auriez-vous des conseils? J'ai bouquiné tout le tuto C en 20h, quelques idées me sont venu mais ça reste un peut flou pour mon cas...

    Je vous remercie,

    Isabelle

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    La solution la plus simple dans ton cas, et qui conserve l'élégance de l'expression mathématique, est d'écrire la fonction psi sous forme récursive, c'est-à-dire que le code de la fonction lui fait référence. L'exemple bateau de la fonction factorielle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    unsigned int fact(unsigned int n) {
        if (n > 1)
            return n * fact(n - 1);
     
        return 1;
    }
    Il existe des contraintes techniques et sémantiques qui limitent ensuite l'application des fonctions récursives en programmation impérative où le compilateur reste assez naïf. Je n'y ferai pas référence ici, saches toutefois qu'en fonction du nombre d'appels récursifs à réaliser cette approche peut vite se révéler impraticable.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    Merci. C'est encore une option que je n'ai pas découverte dans les tutos que j'ai pu lire… Je vais essayer. Si j'ai bien compris, du coup, je n'ai plus besoin de faire deux boucles for, mais juste la fonction récursive ?
    Je risque de faire 5000 itérations au final et sera utilisé pour la résolution d'une autre fonction... donc il faudra peut-être que je passe par autre chose. Mais cela me donne déjà une idée sur les approches informatiques dans mon cas !

    Merci,
    Isabelle

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    @matt_houston: la fonction proposée est déjà récursive...

    @isamaz:

    1. je ne retrouve pas l'intégrale que tu exposes dans ton code... , ta sommation me semble mal positionnée
    2. tu utilises psi tantôt comme une variable psi+=, tantôt comme une fonction psi(j),
    3. tu devrais fractionner tes calculs plutôt que de faire du tout en 1, c'est rapidement illisible!
    4. la récursivité simple te mènera à recalculer plusieurs fois psi pour le même n


    mes conseils:
    calcule petit bout par petit bout, cela te permettra aussi de voir s'il n'y a pas des problèmes de précision (les types du langage C peuvent être sujets à toutes sortes d'erreur: arrondi malheureux, overflow, etc.) et passe à une bibliothèque de calcul de précision si tu rencontres des problèmes (par exemple GMP)
    mémorise les calculs de psi pour n, ou les sommes intermédiaires, encore mieux, pour ne pas avoir à tout recalculer x fois!

  5. #5
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je ne vois qu'une seule fonction ici et elle s'appelle main.

    Ah et j'oubliais : Isamaz, mets-ton code entre balises [CODE] !

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    OK, J'ai essayé de fractionner mais vu que psi(n) dépend de la somme des Psi (i) avec i allant de 1 à n-1 je n'arrive pas à séparer les différentes parties, c'est tout la mon problème. Ce que je n'ai pas mis dans le programme, et que j'ai modifié entre temps, c'est la valeur de Psi(n) pour n=1 qui elle est une valeur finie.
    le coté psi+ et psi(j) c'est que j'ai mimé l'exemple d'une application d'un tuto assimilant ce type de fonction, psi+= .... avec l'utilisation de dx en intervalle défini au début, à une résolution d’intégrale.
    Voici le programme modifié, mais bien sur pas terminer.
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define pi 3.1416
    #define R 8.144621
    #define T 298.15
    #define F 96485
    #define alpha 1
     
    float k1,to,Eimp,di,psi,dt;
    int i, n;
     
    unsigned int fact(unsigned int n) {
        if (n > 1)
            return n * fact(n - 1);
     
        return 1;
    }
    int main(void)
     
    {
        k1=10.0;to=5.5;Eimp=0.6;di=0.001;n=500;
        psi=0.;
        dt=1/n;
        if (i=1)
        psi=(1/sqrt(pi/n))*(1/exp((-alpha*F/(R*T))*(Eimp-k1-log(to))));
       else
              for(i=1;i<n;i=i++);
            {
                psi(n)=(1+1.33*1/(sqrt(pi))*sqrt(dt)*(psi(i-1)*pow(n-i+1,(3/2))+2*pow(n-i,(3/2))+pow(n-i-1,(3/2)))*di)/(exp((-alpha*F/(R*T))*(Eimp-k1-log(to)))+1.33*(1/sqrt(pi))*sqrt(dt));
        }
     
        printf("l'integrale de psi =%3.3f",psi);
        return 0;
        }
    Je te remercie pour tes conseils, cela me fait avancé dans la logique à suivre. Et je m'excuse je me
    mélange les pinceaux avec les différentes options, je me lance dans la programmation depuis peu de temps, je n'ai pas encore tout assimilé et quelques confusions sont encore présentes!

  7. #7
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Il y a en effet de nombreuses erreurs de syntaxe dues à des incompréhensions. C n'est peut-être pas le meilleur choix pour commencer la programmation dans ton cas. Cela étant dit :
    • tu devrais suivre les conseils de stendhal666 lorsqu'il te recommande de procéder par étape, n'écris pas tout sur une ligne et aère ton code (particulièrement les expressions mathématiques). Fais fonctionner ton programme avec une expression simple, puis ajoute des termes au fur et à mesure ;
    • certains termes sont constants, effectue le calcul une fois, stockes le résultat dans une variable puis utilises son nom dans les expressions suivantes ;
    • psi(n) = ... : ça n'existe pas en C, à gauche d'un = (opérateur d'affectation et non de test d'égalité) il y a toujours une zone mémoire où stocker le résultat de l'évaluation de l'expression située à droite (l-value). Ce que tu as écrit est un appel de fonction avec l'argument n, cette fonction doit par ailleurs être définie auparavant ;
    • (3/2) : le résultat de l'évaluation de cette expression est celui de la division entière, 1. Pour obtenir 1.5, il faut que l'un des termes au moins soit un nombre à virgule flottante en écrivant par exemple (3.0 / 2), (3 / 2.), ou encore ((double)3 / 2).

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Quelques remarques :

    1) Tu ne donnes pas la définition de R(n-1).

    2) Au dénominateur, je vois e^(un truc). J'ai oublié le nom de cette lettre.... Pourrais-tu me redonner son nom ? Pourrais-tu aussi nous dire ce que vaut cette constante (ou cette fonction) ?

    3) Pour commencer, je te conseille plutôt une récursivité simple. Tant pis tu recalcules plein de fois les mêmes. L'objectif est d'abord de faire une version qui marche avant de faire une version optimisée.

    4) En continuité du point 4, je vois que tu as réécris pi^(-1/2) en 1/sqrt(pi). C'est juste (merci de me le rappeler, j'avais oublié cette égalité) mais cela éloigne ta fonction de la version originale et n'apporte probablement aucune optimisation pour ton code. Je te conseille dans un premier temps de faire une "bête" traduction de la formule.

    5) Ton problème semble mal exposée. Tu dis par exemple :
    Pour l'instant je me concentre sur la premiere integral qui se résume à l'estimation de cette somme:
    Sauf que tu ne nous montres pas une somme, mais une fonction.

    6) Au début de ton 2e code, je vois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    k1=10.0;to=5.5;Eimp=0.6;di=0.001;
    Que viennent faire ces constantes ici ? A quoi correspondent-elles dans la formule montrée ? Voir le point 5 probablement.

    7) Ton 2e code ne compile sans doute pas, car comme l'a dit stendhal666, tu ne peux pas utiliser psi comme une variable (lignes 23 et 26) puis comme une fonction (ligne 30), alors même que tu n'as pas définie de fonction double psi(int n) !

    Pour l'amusement, j'ai commencé à coder cela en Python. Je sais que ce n'est pas le langage que tu utilises mais je te montre quand même comment j'ai structuré mon code :
    Code python : 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
    25
    26
    27
    28
    29
    30
    31
    32
    import math
     
    n_max = 15
    delta_t = 1.0 / n_max
     
    toto = 1.0
    Rn_1 = 1.0
     
    print(n_max)
    print(delta_t)
     
    def psi(n):
      print("psi({})".format(n))
     
      # There is a common term between numerator and denominator
      common = 4/3 * pow(math.pi, -1/2) * pow(delta_t, 1/2)
     
      # Numerator contains a sum of previous psi for n in 1..n-1
      sum_psi = 0
      for i in range(1, n):
        sum_psi += psi(i) * Rn_1
     
      # Numerator and denominator
      numerator = 1 + common + sum_psi
     
      denominator = math.exp(-toto) + common
     
      # Finally, return a fraction
      return numerator / denominator
     
     
    print(psi(5))

    Comme tu peux le voir, je définie d'abord des constantes, puis une fonction pour calculer psi(n). Cette fonction est récursive, elle calcule les valeurs précédentes de psi(). Tu peux voir aussi que j'ai découpé le calcul de psi(n) en numérateur et dénominateur. J'ai aussi découpé ces 2 membres de mon opération pour plus de lisibilité, mais je suis resté sur la formule de départ, avec des exposant 1/2 plutôt qu'une racine carrée. Et comme tu vois, j'ai encore 2 termes que je ne connais pas : "toto" (la lettre que je ne connais plus...) et R(n-1).


    PS : aurais-tu des valeurs exemples de psi(n) pour certaines valeurs de n, histoire qu'on puisse savoir si on calcule la bonne chose....


    Bien joué Matt_Houston pour les 4/3 qu'il faut écrire 4.0/3.0 ! J'ai complètement omis dans mon code !

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    Merci beaucoup, effectivement j'ai oublié certaines, choses, notamment la fraction 4/3 j'ai passé du temps à savoir comment avoir un résultat décimal et j'ai juste pas du tout mi en pratique
    Merci pour la version python, je vais reprendre tout vos conseil et essayé d'avancer la dessus, je vous ferais parvenir cela au plus vite!
    J’utilise C car du coté scientifique, les personnes qui peuvent me conseiller ne connaissent que ce langage. J'ai plus travaillé sur R-project dans le passé, mais pas vraiment en programmation! Mais tout s'apprend!
    En tout cas merci pour vos conseils.

    Isabelle

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Alors, j'ai repris un peu tout vos conseils, mais j'ai certainement raté quelques étapes ou certaines choses reste flou... Je vais prendre le temps de me replonger dans les définitions en programmation des fonctions,....

    Voici avec plus d'informations sur l’équation, avec la définition mathématique des variables :
    Nom : Captureint.PNG
Affichages : 173
Taille : 3,5 KoNom : Capturedetal.PNG
Affichages : 307
Taille : 46,3 Ko

    Et voici le nouveau programme, j'ai encore du mal avec le psi comment le definir dans la somme et en dehors....
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define pi 3.1416
    #define R 8.144621
    #define T 298.15
    #define F 96485
    #define alpha 1
     
    float k1,to,Eimp,psi,dt,Rni,common, ksi,sum_psi;
    int i, nmax, n;
     
    int main ()
    {
        /* je défini ici les paramètre a fixé avant mon calcul*/
        nmax=5;
        n=5;
        dt=1/nmax;
        common=4.0/3*pow(pi,(-1.0/2))*pow(dt,(1.0/2));
     
        /*avec k1,to et Eimp qui sont des constantes dans ksi*/
        k1=10.0;to=5.5;Eimp=0.6;
        ksi=-alpha*F/R*T*(Eimp-k1-(1.0/2)*log(to));
     
        sum_psi=0.;
        /* pour que ma somme fonctionne il faut que le psi pour i=1 est définit selon l'equation suivante */
           if (i=1)
        {
                        /* voici le fameux R(n-i) que j'ai nommé du coup Rni, ici pour i=1*/
        Rni=pow(n,(3.0/2))-2*pow(n-1,(3.0/2))+pow(n-2,(3.0/2));
        psi=pow(pi*dt,(-1.0/2))*1.0/(1+exp(ksi));
        }
        else if (i>1)
            /* est qu'ensuite il va récuperer automatiquement la valeur du psi pour i=1 si j'inclue la variation de i de 1 à n-1 ?*/
        for(i=1;i<n;i=i++)
               /* et voici le fameux R(n-i) que j'ai nommé du coup Rni*/
            Rni=pow(n-i+1,(3.0/2))-2*pow(n-i,(3.0/2))+pow(n-i-1,(3.0/2));
            /*Alors le psi ici ne fonctionne pas j'ai encore du mal avec cette histoire de fonction ou fonction pointer...*/
     
            psi=(1+common*(psi(1)*Rn1+sum_psi*Rni;
            sum_psi+=psi(i)*Rni;
     
     
     
                      printf(psi=%3.3f, psi(n));
        return 0
    }
    Merci encore,

    isabelle

  11. #11
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    J'ai l'impression qu'il te manque tout simplement la notion de fonction...

    Le sens de ces expressions est assez différent de ce qu'il est en mathématique mais tu peux utiliser dans tes programmes des variables et des fonctions:
    -aux variables tu assignes des valeurs, qui peuvent être modifiées ou non (const / pas const)
    - les fonctions te permettent (entre autres) de calculer des valeurs à partir d'autres valeurs. Donc dans ton programme, tu devrais isoler les différentes procédures de calcul dépendant d'une valeur dans différentes fonctions; il y en a 2 si je ne me trompe pas: psi et R, avec pour signatures:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double psi(int n, int n_max);
    double r(int n);
    Pour donner une idée du squelette:

    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 "math.h"
    #include "stdio.h"
     
    double r(int n) {
      double result = 0;
      // calculer result;
      return result;
    }
     
    double psi(int n, int n_max) {
      double result = 0;
      // calculer result
      return result;
    }
     
    int main() {
      int n = 200, n_max = 1000;
      printf("psi(%d, %d) = %f\n", n, n_max, psi(n, n_max));
    }
    Cela permet d'aérer le code et de tester les différentes parties séparément. Dans le même esprit, tu pourrais créer une fonction double ksi(double e_imp, double theta, double k1) si tu souhaites faire évoluer ton programme afin qu'il permette de tester différents paramètres de configuration.

    Maintenant pour le problème du calcul récursif de psi, tu as 2 solutions:

    récursivité:
    ça marche grosso modo comme l'induction mathématique: il te faut un cas 0 et un cas n+1. Le cas 0 est simple, c'est, si j'ai bien lu, 1 / ( (pow(e, -ksi) * ...) puisque la somme ne contient aucun élément donc ça donnerait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    double psi(int n, int n_max) {
      if (n == 1) return 1 / ( (pow(e, -ksi) * ... ) // cas 0
      else {
        // calculer les différents paramètres
        double sum = 0;
        for (int i = 1; i < n; ++i) sum += psi(i-1, n_max) * R(i-1);
        return (1 + a * sum) / b;
      }
    }
    le désavantage c'est que tu vas calculer psi(n-1), psi(n-2), ... de très nombreuses fois: tu répètes les calculs à chaque fois comme s'ils n'avaient jamais été faits.

    la conservation des résultats précédents est l'autre solution mais fait appel à des notions un tout petit peu plus avancées en programmation.

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    merci, effectivement j'ai encore du mal avec le terme fonction et "return" qui ne me parle pas trop encore.
    Je vais essayer ce nouveau type d'organisation. A terme, je vais devoir dans tous les cas enregistrer les données pour pouvoir les utiliser dans une autre intégrale... et enfin utiliser chaque résolution d’intégrale dans une équation afin de tracer une courbe.... Donc je suis juste au début de mon calvaire... mais j'aurais de l'aide en live bientôt, pour l'instant je m’habitue au langage C

  13. #13
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    en informatique de manière générale, une fonction est un bloc d'instruction créant une valeur en fonction de ses paramètres (et provoquant des effets secondaires, tels qu'un affichage).

    Le return signifie simplement que l'évaluation de la fonction se termine à cette instruction, et que l'expression d'appel de la fonction vaut la valeur indiquée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int f(int x) {return x*x;}
     
    int main() {
       int d = f(7);
    }
    ici, f(7) est une expression. C'est l'appel de la fonction f avec la valeur 7 affectée au paramètre a.
    f retourne la valeur de l'expression a*a. Comme a vaut 7 dans notre cas, la fonction retourne 7.

    Exactement comme en math, on aurait attendu que la fonction définie par "f: x -> x*x" donne f(7) = 49.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  14. #14
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Ne le prends pas mal Isamaz mais tu sembles vraiment larguée. Je pense qu'à ce niveau-là il te faut revoir les bases d'algorithmique. Tu ne sais visiblement même pas appréhender le control flow avec découpage en procédures et fonctions. Si en plus - puisque la forme récursive est out d'après le complément d'énoncé posté ci-avant - il faut que tu te tapes une gestion de tableaux et une implémentation itérative, le tout en C...

    C'est quoi la nature de ce travail ? Un exercice de cours ? Une tâche à accomplir dans le cadre de ton boulot ? Tu as seulement besoin du résultat pour avancer sur autre chose ?

    Peut-être que dans tes cas d'utilisation présent et futurs un langage fonctionnel (OCaml, m'entends-tu ?) serait plus approprié ? La façon de donner des instructions à la machine y est plus proche de l'expression mathématique. En plus c'est top pour la récursion.

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Merci pou ces encouragements...
    Ce projet permet de modéliser des données, pour compléter une étude expérimental sur des capteurs électrochimiques.... Je ne suis donc pas du tout dans le domaine de l'info, je suis en thèse en électrochimie. Les collègues qui m'aident pour l'établissement des relations mathématiques dans mon cas expérimentales connaissent C, je souhaite donc rester sur C pour avoirun regard scientifique de leur part sur le programme final.
    Je te rassure Matt_Houston, un ami va me venir en aide en fin de semaine (comme dit précédemment), mais afin de bien comprendre j'ai besoin d'avancer au maximum sur ces programmes.
    Merci leternel, je comprends beaucoup mieux.

  16. #16
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Ce que je voulais dire c'est que le programme que tu cherches à écrire n'est pas bien complexe au final, pour quelqu'un qui sait déjà programmer s'entend. Si ton collègue connais le C il va te l'écrire en quoi, une ou deux heures ? D'où la question : est-ce l'exercice ou le résultat qui importe ? I.e. : est-ce que tu ne ferais pas mieux d'avancer sur autre chose en attendant ton programmeur ?

    Ça ne fait pas avancer ton schmilblick j'en suis conscient mais ce sera la même si on continue à te parler de choses que tu ne comprends pas.

    Peace.

  17. #17
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    D'un autre côté, c'est bien de vouloir avancer, mais il conviendrait alors de chercher un cours (parmi ceux que nous proposons, par exemple).

    L'idée générale derrière l'écriture d'un programme, c'est d'expliquer à un ordinateur une méthode pour résoudre un problème, et dans une langue qu'il connait.
    Il faut donc savoir comment résoudre le problème pour pouvoir l'expliquer.

    Le reste, c'est une histoire de syntaxe et de style.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  18. #18
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Si tu es en thèse d'électro-chimie, on ne va pas t'aider de la même manière qu'un étudiant en 1ère année de fac info

    Je pense aussi que c'est utile que tu comprennes comme ça fonctionne puisqu'après tout, tu es directement concernée. Mais je suis aussi d'accord que l'exercice est un peu costaud pour un débutant. Ecrire la version simple de psi(n) comme je l'ai donné plus haut, c'est simple ; écrire une version optimisée qui va calculer psi(1) à psi(5000) en moins de 3 jours (de temps d'exécution), c'est un peu plus ardu.

    Dans la suite du code que j'ai proposé plus haut, j'ai fait la version qui utilise un tableau pour stocker les résultats intermédiaires. Je n'ai pas rajouté les éléments supplémentaires que tu as donné. Il est iso-fonctionnel avec mon premier code. Je te le donne au cas où ça puisse te servir :

    Code python : 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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    import math
     
    n_max = 15
    delta_t = 1.0 / n_max
     
    toto = 1.0
    Rn_1 = 1.0
     
    #print(n_max)
    #print(delta_t)
     
    common = 4.0/3.0 * pow(math.pi, -1.0/2.0) * pow(delta_t, 1.0/2.0)
     
    '''
    The cache to store psi(1..n-1). The i-th element is psi(i).
    '''
    psi_cache = []
     
    '''
    A internal function that computes psi(n) using the cache.
    The cache is assumed to have been filled previously.
    '''
    def psi_internal(n):
      if n == 0:
        return 0
      if n == 1:
        return 1
     
      # There is a common term between numerator and denominator
      common = 4.0/3.0 * pow(math.pi, -1.0/2.0) * pow(delta_t, 1.0/2.0)
     
      # Numerator contains a sum of previous psi for n in 1..n-1
      sum_psi = 0
      for i in range(0, n-1):
        sum_psi += psi_cache[i] * Rn_1
     
      # Numerator and denominator
      numerator = 1 + common + sum_psi
     
      denominator = math.exp(-toto) + common
     
      # Finally, return a fraction
      return numerator / denominator
     
     
    '''
    A public function to compute psi(n).
    It will will the cache with psi(1..n-1) using psi_internal()
    and will finally return psi(n).
    '''
    def psi(n):
      global psi_cache
      psi_cache = [0] * (n - 1)
     
      for i in range(1, n):
        psi_cache[i - 1] = psi_internal(i)
     
      return psi_internal(n)
     
    if __name__ == "__main__":
      print("Version 2")
     
      print(psi(1))
      print(psi(2))
      print(psi(5))
      print(psi(10))

    Bon courage.

  19. #19
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    Merci pour tout ces conseils, effectivement c'est important que je m'investisse même si le début est compliqué. J'ai cependant comprendre beaucoup plus facilement les modifications que mon ami a fait sur le programme déjà créer et du coup j'ai pu le faire évoluer par la suite de manière autonome...
    Ou presque,
    Voici le programme que nous avons créer, il tournait jusqu'à vendredi, je vais modifier des chose vis-à-vis des calculs, mais sinon il me donnait un tableau en .CSV

    Aujourd'hui, il me met directement une erreur dès la première ligne, je ne comprend pas pourquoi car je n'ai pas modifier cette partie, est ce un problème avec Code::blocks?
    dès le premier double r (int x)
    il annonce : error: expected '=', ',', ';', 'asm' or '__attribute__' before 'double'
    (pour info il le fait pour tous les "double" et meme si je remplace avec "int" il n'accepte pas non plus).
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    
    
    #define PI 3.14159265359
    #define R 8.144621
    #define T 298.15
    #define F 96485
                                                                                                                                                                                                      Q
    #define E_IMP 0.6
    #define ALPHA 0.5
    #define K1 0.1
    #define K2 2E-7
    #define TAU 1.0
    #define N_MAX 60
    #define S 1.96E-7
    #define C 0.01
    #define D 0.00001
    
    /// calcul de R(x)
    double r(int x)
    {
        return pow(x+1, (3.0/2)) - 2*pow(x, (3.0/2)) + pow(x-1, (3.0/2));
    }
    
    /// calcul de psie etoile (n) avec mémoire des valeurs déjà calculées
    double psie(int n)
    {
        static const double dt = 1.0 / N_MAX;
        static const double ksi = -ALPHA*F/(R*T) * (E_IMP-K1-0.5*log(TAU));
        static const double common = 4.0/3*pow(PI, (-1.0/2))*pow(1.0/N_MAX, (1.0/2));
    
       if(n==1)
        {
            return pow(PI*dt,(-1.0/2))*1.0/(1+exp(-ksi));
        }
        else
        {
            double sum = 0;
            int j;
            for (j=1;j<n;++j)
            {
                sum += psie(j)*r(n-j);
            }
            return(1+common*sum)/(exp(-ksi)+common);
        }
    
        static double mem[N_MAX];
        mem[0] = pow(PI*dt,(-1.0/2))*1.0/(1+exp(-ksi));
    
        if(mem[n-1] == 0)
        {
            double sum = 0;
            int j;
            for (j=1;j<n;++j)
            {
                sum += psie(j)*r(n-j);
            }
            mem[n-1] = (1+common*sum)/(exp(-ksi)+common);
        }
        return mem[n-1];
    }
    
    /// calcul de omega(n) avec mémoire des valeurs déjà calculées
    double omega(int n)
    {
        static const double dt = 1.0 / N_MAX;
        static const double p = K2 * pow(TAU,1.0/2);
        static double mem[N_MAX];
    
        mem[0] = (p*dt*psie(n=1))/(2+p*dt*psie(n=1));
    
        if(mem[n-1] == 0)
        {
            double sum = 0;
            int j;
            for (j=1;j<n;++j)
            {
                sum += (1-omega(j))*psie(j);
            }
            mem[n-1] = (p*dt*psie(n)+sum)/(2+p *dt*psie(n));
        }
        return mem[n-1];
    }
    /// calcul de psi(n) avec mémoire des valeurs déjà calculées
    double psi(int n)
    {
        return (1-omega(n=N_MAX))*psie(n=N_MAX);
    }
    
    /// calcul de i avec mémoire des valeurs déjà calculées
    double i(int n)
    {
            double sum = 0;
            double t;
            static double mem[N_MAX];
            mem[0] = 0;
    
            {
                 mem[n-1] = psi(n=N_MAX)*F*S*C*pow(D,1.0/2)/pow((TAU),1.0/2);
            }
        return mem[n-1];
    }
    
    int main()
    {
        /// création du nom de fichier avec tous les paramètres
        //char* filename = "resultat.csv";
        char *filename = malloc(255*sizeof(char));
        sprintf(filename,"filename_%d_%1.1f_%1.1f_%1.1f_%1.1f", N_MAX, ALPHA, E_IMP, TAU, K1);
        strcat(filename, ".csv");
    
        /// verifier que le fichier est bien ouvert
        FILE *fp = fopen(filename, "w");
        if(fp == NULL) {
            printf("Cannot open file.\n");
            exit(1);
        }
    
        /// on fait tous les calculs
        int j;
        for (j=1; j<=N_MAX; ++j)
        {
            //printf("psi(%d) = %e\n", i, psi(i));
            //fprintf(fp, "%e\n", psi(i));
            printf("psie,omega(%d|%f),i = %1.2e,%1.2e,%1.2e\n",  (j*TAU/N_MAX), psie(j), omega(j),i);
            fprintf(fp, "%1.2e,%1.2e,%1.2e\n", (j*TAU/N_MAX), psie(j), omega(j),i);
        }
        fclose(fp);
        return 0;
    }
    J'avoue que je ne comprend pas du tout, auriez-vous des idées ou des conseils?

    Merci,

  20. #20
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    as-tu subi une mise à jour du compilateur ou de Code::Blocks ?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

Discussions similaires

  1. boucle For avec variable variant
    Par frogs dans le forum Langage
    Réponses: 4
    Dernier message: 19/08/2011, 11h37
  2. [XL-2003] Cellule = nom variable avec variable définie dans VBA
    Par cailloup dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 10/08/2011, 13h08
  3. Réponses: 22
    Dernier message: 19/01/2010, 12h59
  4. Condition avec variable comprise dans un interval
    Par lumycaan dans le forum Langage
    Réponses: 2
    Dernier message: 26/11/2009, 22h36
  5. [MySQL] Problème de syntaxe avec variable utilisée dans fonction PHP et MySQL
    Par redvivi dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 19/03/2008, 21h07

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