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 :

Nombre à virgule dans un Cosinus


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut Nombre à virgule dans un Cosinus
    Bonjour à tous,

    Dans le cadre d'un projet en école d'ingénieur, je dois calculer la racine d'une fonction f(x)=cos(x)-x+PI/2 par la méthode du point fixe. Voici mon code ci-joint, mais je ne parviens à faire prendre la valeur de x0 à mon cosinus car ce dernier ne prends pas les double mais que des entiers. Je ne sais donc pas comment faire...

    Si vous pouviez m'aiguiller
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define PI 3.141592653
     
    // Prototypes
    double toSolve (double x);
    double resolution (double x0);
     
     
    int main()
    {
        // Déclarations des variables
     
        double x0;                              // Valeur initiale
        double racine;                          // Position à laquelle l'avion touche le sol
     
        // On commence par entrer la valeur initale
        printf("Entrez la valeur initiale : ");
        scanf("%lf",&x0);
     
        // Calcul de la racine de la fonction
     
        racine=resolution(x0);                           // On appelle uniquement la fonction resolution pour calculer la racine de la fonction donnée
     
        printf("\nLa racine de notre fonction est : %lf \n",racine);
     
        return 0;
    }
     
    double toSolve (double x)
    {
        double y;
     
        y=cos(x)+(PI/2);                                         // Ecriture de la fonction donnée par le sujet
     
        return y;                                                // On retourne la valeur de y image de la fonction en x
    }
     
    double resolution (double x0)
    {
          while (fabs(x0-toSolve(x0))>1e-10)                  // Lorsque l'écart entre x et f(x) est supérieur à l'erreur donnée,
            {
                x0=toSolve(x0);                                  // On donne la valeur de l'ancienne image à x au rang suivant
            }
     
        return x0;
    }

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tennis488 Voir le message
    Bonjour à tous,
    Salut

    Citation Envoyé par tennis488 Voir le message
    ...mais je ne parviens à faire prendre la valeur de x0 à mon cosinus car ce dernier ne prends pas les double mais que des entiers.
    Je ne comprends pas cette phrase. La fonction cos a pour signature double cos(double). Elle est donc bien prévue pour recevoir un double et non pas un int. De fait, chez-moi ton code fonctionne parfaitement. Sauf concernant la boucle car la valeur x0-toSolve(x0) oscille indéfiniment entre pi/2+epsilon et pi/2-epsilon et ne tend jamais vers 0 ce qui donne une boucle infinie mais cela n'a rien à voir avec un souci lié à cos(x).

    Sinon concernant ton code, dans la fonction toSolve() la variable "y" ne sert à rien ainsi que les parenthèses à PI/2. Et dans la fonction resolution() ce serait bien d'éviter d'appeler deux fois "toSolve()" (on n'appelle pas deux fois une fonction alors que le contexte d'appel n'a pas changé). Et pour les prototypes, tu n'es pas obligé de donner un non aux paramètres.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Salut


    Je ne comprends pas cette phrase. La fonction cos a pour signature double cos(double). Elle est donc bien prévue pour recevoir un double et non pas un int. De fait, chez-moi ton code fonctionne parfaitement. Sauf concernant la boucle car la valeur x0-toSolve(x0) oscille indéfiniment entre pi/2+epsilon et pi/2-epsilon et ne tend jamais vers 0 ce qui donne une boucle infinie mais cela n'a rien à voir avec un souci lié à cos(x).

    Sinon concernant ton code, dans la fonction toSolve() la variable "y" ne sert à rien ainsi que les parenthèses à PI/2. Et dans la fonction resolution() ce serait bien d'éviter d'appeler deux fois "toSolve()" (on n'appelle pas deux fois une fonction alors que le contexte d'appel n'a pas changé). Et pour les prototypes, tu n'es pas obligé de donner un non aux paramètres.
    D'accord, je comprends vos remarques et je vous remercie de votre aide. Cependant, je ne sais pas comment faire pour ne plus avoir de valeur qui oscillent et faire en sorte que la valeur x0-toSolve(x0) tendent vers 0 et que mon programme s'arrête lorsque cette valeur est inférieure à ma précision de 10^-10.

    Ci-joint la fonction toSolve est-elle mieux comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    double toSolve (double x)
    {
        return (cos(x)+(PI/2));
    }

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tennis488 Voir le message
    Cependant, je ne sais pas comment faire pour ne plus avoir de valeur qui oscillent et faire en sorte que la valeur x0-toSolve(x0) tendent vers 0 et que mon programme s'arrête lorsque cette valeur est inférieure à ma précision de 10^-10.
    Là il y a deux questions en une seule
    1. comment faire pour que x0-toSolve(x0) tende vers 0
    2. comment détecter l'oscillation et, de fait, la boucle infinie qui en résulte

    Le premier point est un point purement mathématique. Si une fonction ne tend pas vers 0 (ni vers aucune autre valeur finie), alors elle ne tend pas vers 0 et rien ne peut changer ce fait
    Le second point lui est plus du domaine de la programmation. On peut par exemple mémoriser les n derniers résultats et à chaque nouveau calcul on regarde si ce nouveau calcul a déjà été trouvé dans les n précédents. Plus "n" sera grand plus on a de chances de sortir plus vite de la boucle.
    Il y a quand-même un détail que je remarque: la fonction initiale est f(x)=cos(x)-x+pi/2 ou bien f(x)=-x + cos(x) + pi/2. Or ton code lui calcule x-cos(x) - pi/2 soit -f(x). La fonction est-elle impaire ?

    PS: en supprimant "+pi/2" chez-moi ça sort un résultat direct (en saisissant 4.5 comme valeur initiale).

    Citation Envoyé par tennis488 Voir le message
    Ci-joint la fonction toSolve est-elle mieux comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double toSolve (double x)
    {
        return (cos(x)+(PI/2));
    }
    Mieux en effet. Au-moins la variable inutile a disparu. Toutefois la division étant prioritaire sur l'addition ne nécessite pas de parenthèses. De même pas non plus besoin de parenthèses au return
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    double toSolve (double x) {
        return cos(x) + PI/2;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Il y a quand-même un détail que je remarque: la fonction initiale est f(x)=cos(x)-x+pi/2 ou bien f(x)=-x + cos(x) + pi/2. Or ton code lui calcule x-cos(x) - pi/2 soit -f(x). La fonction est-elle impaire ?

    PS: en supprimant "+pi/2" chez-moi ça sort un résultat direct (en saisissant 4.5 comme valeur initiale).
    Oui en effet, la fonction initiale dont je dois calculer la racine est f(x)=cos(x)-x+PI/2, donc je regarde l'abscisse du point fixe entre la fonction y=xet g(x)=cos(x)+PI/2, et normalement je dois tomber directement sur la racine lorsque la précision est atteinte...

    Comme vous, j'avais déjà réalisé cet exercice juste avec g(x)=cos(x) et j'avais un résultat directement, mais là le PI/2 m'embête

    Citation Envoyé par Sve@r Voir le message
    la fonction initiale est f(x)=cos(x)-x+pi/2 ou bien f(x)=-x + cos(x) + pi/2
    Pour moi, il s'agit de la même fonction initiale ...

    De plus je vous ai tracer les trois courbes qui sont utiles au problème, et normalement la racine est égale à 1,57..

    Nom : Tracé des fonctions.PNG
Affichages : 204
Taille : 127,3 Ko

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    D'accord, je comprends mieux. L'intersection de la courbe verte et rouge (que tu as je pense tracé à partir de https://www.mathe-fa.de) donne x=1.57 et si on calcule l'équation de entre y=x et y=cos(x) + pi/2 ça donne cos(x) + pi/2 - x = 0

    Bon j'ai fait un truc qui détecte l'oscillation. Mais de par la précision, j'ai été obligé de réduire l'epsilon à 1e-3.
    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    #define PI 3.141592653
    #define TMP			10
     
    // Prototypes
    double toSolve(double);
    double resolution(double);
    void push(double, double[], size_t);
    size_t inTab(double, double[], size_t);
     
    int main()
    {
    	// Déclarations des variables
     
    	double x0;							  // Valeur initiale
    	double racine;						  // Position à laquelle l'avion touche le sol
     
    	// On commence par entrer la valeur initale
    	printf("Entrez la valeur initiale : ");
    	scanf("%lf", &x0);
    	printf("x=%lf\n", x0);
     
    	// Calcul de la racine de la fonction
    	racine=resolution(x0);						   // On appelle uniquement la fonction resolution pour calculer la racine de la fonction donnée
     
    	printf("\nLa racine de notre fonction est : %lf \n",racine);
     
    	return 0;
    }
     
    double toSolve(double x)
    {
    	return cos(x) + PI/2;
    }
     
    // Insère un élément au début d'un tableau en décalant tout le reste
    void push(double x, double tmp[], size_t n) {
    	memmove(tmp+1, tmp, (n-1) * sizeof(*tmp));
    	tmp[0]=x;
    }
     
    // Vérifie si un élément est présent dans un tableau
    size_t inTab(double x, double tmp[], size_t n) {
    	size_t i;
    	for (i=0; i < n; i++) {
    		if (fabs(tmp[i] - x) < 1e-3) return i+1;
    	}
    	return 0;
    }
     
    double resolution (double x0)
    {
    	double tmp[TMP]={0};
     
    	while (1) {
    		x0=toSolve(x0);
    		printf("x0=%lf\n", x0);
    		if (inTab(x0, tmp, TMP)) break;
    		push(x0, tmp, TMP);
    	}
    	return x0;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    688
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 688
    Par défaut
    Citation Envoyé par tennis488 Voir le message
    Cependant, je ne sais pas comment faire pour ne plus avoir de valeur qui oscillent et faire en sorte que la valeur x0-toSolve(x0) tendent vers 0 et que mon programme s'arrête lorsque cette valeur est inférieure à ma précision de 10^-10.
    Salut,

    C'est normal d'avoir une oscillation car c'est le mode d'approximation de la valeur recherchée. Le problème c'est que tu demandes une trop grande précision et que tu n'as pas le temps d'attendre le résultat. À 1e-3 c'est rapide, à 1e-4 c'est raisonnable, au-delà il faut s'armer de patience.

    Aussi à la place de pi/2 tu peux utiliser M_PI_2, c'est pris en charge par la plupart des compilateurs, regarde aussi les options de compilation "fast math" qui améliorent les temps de calcul.

    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
    #include <stdio.h>
    #define _USE_MATH_DEFINES // M_PI_2
    #include <math.h>
     
    double f(double x)
    {
        return cos(x)+M_PI_2;
    }
     
    int main()
    {
        double x= 0.0;
        const double precision= 1E-3;
        double y;
        while (y= f(x), fabs(y-x)>precision)
            x= y;
        printf("x=%f", x);
     
        return 0;
    }

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2021
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2021
    Messages : 6
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Salut,

    C'est normal d'avoir une oscillation car c'est le mode d'approximation de la valeur recherchée. Le problème c'est que tu demandes une trop grande précision et que tu n'as pas le temps d'attendre le résultat. À 1e-3 c'est rapide, à 1e-4 c'est raisonnable, au-delà il faut s'armer de patience.
    Le problème, c'est que la précision est imposée à eps=1e-10 !

    Le calcul devient alors interminable, est-ce qu'il ne faudrait pas regarder dans l'optimisation des fonctions écrites afin de rendre plus rapide la convergence vers la racine finale 1,57...?

  9. #9
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    688
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 688
    Par défaut
    La progression est ici linéaire mais on peut très bien augmenter le degré de convergence. Il peut être d'ordre quadratique (2nd degré), cubique, quartique... Par contre, est-ce ce que ça rentre dans le cadre de ton cours, est ce que ça répond à ce qui est attendu de toi, ça je ne sais pas. Voici tout de même un exemple:

    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
    #include <stdio.h>
    #define _USE_MATH_DEFINES //M_PI_2: 1.57079632679489661923
    #include <math.h>
     
    inline double f(double x)
    {
        return cos(x)+M_PI_2;
    }
     
    //convergence accelerator,
    //  here quadratic example with delta-squared method (Aitken? Steffensen?)
    inline double g(double y0)
    {
        double y1= f(y0);
        double y2= f(y1);
        return y0-pow(y1-y0,2)/(y2+y0-2*y1); 
    }
     
    int main()
    {
        double x= 0.0;
        const double precision= 1E-10;
        double y;
        while (y= g(x), fabs(y-x)>precision)
            x= y;
        printf("x=%.20f", x);
     
        return 0;
    }

Discussions similaires

  1. Réponses: 5
    Dernier message: 16/05/2014, 14h38
  2. [Dojo] Nombre à virgule dans NumberSpinner
    Par VinceCBA dans le forum Bibliothèques & Frameworks
    Réponses: 4
    Dernier message: 15/04/2013, 09h51
  3. Nombre à virgule dans un champ dynamique
    Par pierrot53 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 19/05/2009, 22h44
  4. récupérer un nombre à virgule dans un fichier Excel
    Par Piccolo_son dans le forum C++
    Réponses: 3
    Dernier message: 18/06/2007, 09h44
  5. Ecriture de nombres à virgule dans un fichier
    Par Berliozz dans le forum VBScript
    Réponses: 2
    Dernier message: 02/09/2006, 15h36

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