Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 22/05/2017, à 17:31

plouf1221

reference indéfini vers sqrt [RESOLU]

Bonsoir,

J'ai fait une petite fonction nommée proche_zero qui prend en paramètre un tableau et qui renvoi la valeur la plus proche de zero.
J'ai bien inclus le fichier math.h mais le compilateur ne reconnaît pas la fonction sqrt avec le message d'erreur suivant :

gcc test.c -o test.exe -std=c99
/tmp/ccnZUX5K.o : Dans la fonction « proche_zero » :
test.c:(.text+0x298) : référence indéfinie vers « sqrt »
collect2: error: ld returned 1 exit status

fonction proche_zero :

double proche_zero (double* tableau)
{
        int nbr_element = sizeof (tableau) / sizeof (*tableau);
        int min_pos = 0;

        double* p = malloc (sizeof (*tableau) * nbr_element);

        for (int i = 0; i < nbr_element; i++)
                p[i] = tableau[i];

        for (int i = 0; i < nbr_element; i++)
                p[i] = sqrt (p[i] * p[i]);

        for (int i = 0; i < nbr_element; i++)
                if (p[i] < p[min_pos])
                        min_pos = i;

        free (p);
        return tableau[min_pos];
}

Le main :

 int main (int argc, char* argv[])              
 {
         double tableau[] = { 1.0, -3.4, -5.6 };
         printf ("%g", proche_zero (tableau));
 
         return EXIT_SUCCESS;
 }

Pourtant je respecte bien le prototype de la fonction en prenant des doubles et en retournant un double de même que le nom de la fonction
et j'ai bien inclus le header math.h

Je ne comprends pas ce qui cloche.

Dernière modification par plouf1221 (Le 23/05/2017, à 13:32)

Hors ligne

#2 Le 22/05/2017, à 19:20

alduc31

Re : reference indéfini vers sqrt [RESOLU]

Salut,

Manque la librairie qui contient sqrt (libm) :

gcc test.c -o test.exe -std=c99 -lm

Pas besoin d'extension .exe sous linux.


Asus UX325EA oled (i5-1135G7,16Go) avec Lunar 23.04 (base xubuntu modifiée)

Hors ligne

#3 Le 22/05/2017, à 20:31

claudius01

Re : reference indéfini vers sqrt [RESOLU]

Bonsoir,

Effectivement, et désolé plouf1221, cela fait partie d'un autre "bordel" qu'est:
- Mais bon sang, j'ai mis tous les include, et mon exécutable ne se produit pas (phase d'édition de liens pour être plus précis en échec)
- Mais comment font-ils pour savoir qu'il faut mettre -lm pour une librairie qui s'appelle ... libm.so dans le cas le plus simple (j'ai vu des libm.so.5 et même des libm.so.5.0.9 ;-)

Allez, je te laisse chercher un peu car cela est très instructif...

NB1: Apprendre à apprendre est la meilleure pédagogie pour peu que l'on veuille s'investir un peu et même beaucoup
NB2: Et encore, c'est relativement plus facile avec le web maintenant ... encore que ;-))

Hors ligne

#4 Le 23/05/2017, à 13:24

plouf1221

Re : reference indéfini vers sqrt [RESOLU]

Bonsoir,

En me renseignant un peu l'option -lm du compilateur signifie l=link et m=math.
Je suppose que si j'utilise d'autres fonctions que j'ai vu ici par exemple https://www.gnu.org/software/libc/manua … Index.html
et y en a tout de même pas mal, il faudra à chaque fois que je précise sur la ligne de commande la librairie que j'utilise.
Cela risque de me rallonger pas mal ma ligne de commande. D'autant que je ne connais pas forcément les autres noms des autres librairies.
Mais bon on en est pas encore la et loin de la.

Je commence à regretter de ne pas avoir adopter la philosophie d'un IDE, juste clic on the button and basta.
Merci pour vos réponses.

PS : je mets le .exe pour m'y retrouver je sais que ce n'est pas obligatoire mais je trouve cela nécessaire

Dernière modification par plouf1221 (Le 23/05/2017, à 13:42)

Hors ligne

#5 Le 23/05/2017, à 13:44

alduc31

Re : reference indéfini vers sqrt [RESOLU]

Pour les fonctions mathématiques de ton lien, -lm suffit. Pour la plupart des autres, rien besoin de plus.

Avec un IDE, même s'il inclus d'office -lm, il faudra ajouter les librairies que tu utilises (ça ne se fera pas tout seul). Si tu fais un programme graphique en GTK, faudra indiquer les lib GTK et aussi le chemin pour les includes...

Il y a pkg-config qui permet de configurer les lib/chemins d'include pour gcc. Par exemple pour utiliser les lib GTK3 :

pkg-config --cflags --libs gtk+-3.0

retourne :

-pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/mirclient -I/usr/include/mircore -I/usr/include/mircookie -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0

Pour l'utiliser :

gcc prog.c -o prog -lm `pkg-config --cflags --libs gtk+-3.0`

Asus UX325EA oled (i5-1135G7,16Go) avec Lunar 23.04 (base xubuntu modifiée)

Hors ligne

#6 Le 23/05/2017, à 20:24

grigouille

Re : reference indéfini vers sqrt [RESOLU]

$ man 3 sqrt | grep Link
       Link with -lm.

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#7 Le 23/05/2017, à 20:31

grigouille

Re : reference indéfini vers sqrt [RESOLU]

plouf1221 a écrit :
double proche_zero (double* tableau)
{
        int nbr_element = sizeof (tableau) / sizeof (*tableau);

À mon avis, il y a un problème ici. Pour moi, nbr_element est une constante qui dépend de ton système d'exploitation.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#8 Le 23/05/2017, à 20:49

grigouille

Re : reference indéfini vers sqrt [RESOLU]

Tu parcours trois fois ton tableau pour trouver la valeur la plus petite en valeur absolue ? Tu utilises sqrt pour cela ?


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#9 Le 24/05/2017, à 17:05

plouf1221

Re : reference indéfini vers sqrt [RESOLU]

Oui si tu as mieux je t'écoute mais en utilisant seulement sqrt je pense que t'as pas le choix faudra parcourir trois fois le tableau.
Faudra de toute façon recopier les valeurs du tableau pour ne pas altérer le tableau --> une boucle
Un calcule pour trouver la valeur la plus proche de zéro  --> une boucle.
Ce qui te fait deux boucles au mieux.
Moi j'en ai rajouté une afin de trouver le minimum des valeurs absolu.
Je ne vois pas comment tu peux faire autrement sans touché au tableau et en utilisant sqrt.
Mais si tu as mieux il suffit de me montrer ton code au mieux tu feras deux boucles.

Pour moi y a pas de problème la variable nbr_element est indépendante du systeme d'exploitation tout est proportionnel
si ton int est codé sur 4 octets et que tu as un tableau[4] => 16 octets en mémoire mais toujours 4 élements = 16 / 4
si ton int est codé sur 6 octets et que tu as un tableau[4] => 24 octets en mémoire mais toujours 4 élements = 24 / 6

Dernière modification par plouf1221 (Le 24/05/2017, à 17:06)

Hors ligne

#10 Le 24/05/2017, à 17:10

alduc31

Re : reference indéfini vers sqrt [RESOLU]

Valeur absolue d'un double --> fabs()


Asus UX325EA oled (i5-1135G7,16Go) avec Lunar 23.04 (base xubuntu modifiée)

Hors ligne

#11 Le 24/05/2017, à 17:18

plouf1221

Re : reference indéfini vers sqrt [RESOLU]

Merci une autre fonction dans la boutique cool

En faite je vais simplement remplacer sqrt (p[i] * p[i]) par fabs (p[i])

J'ai bien toujours trois boucle.
Faut bien que je trouve le minimum parmi les valeurs absolus.

Dernière modification par plouf1221 (Le 24/05/2017, à 17:36)

Hors ligne

#12 Le 24/05/2017, à 17:43

Nasman

Re : reference indéfini vers sqrt [RESOLU]

A défaut de fabs tu peux aussi prendre x si x>=0 et -x si x<0, je pense que c'est plus rapide que de prendre la racine carrée d'un carré.


PC fixe sous Bionic 64 bits et portable avec Focal 64 bits

Hors ligne

#13 Le 24/05/2017, à 18:16

plouf1221

Re : reference indéfini vers sqrt [RESOLU]

A mon avis dans le code de fabs y a exactement ce que tu dis Nasman donc cela revient exactement au même.
C'est ce qu'il dise ici https://www.gnu.org/software/libc/manua … index-fabs
Même si y a pas le code source pour vérifier à mon avis c'est kif kif tout ça.

Hors ligne

#14 Le 24/05/2017, à 18:28

Nasman

Re : reference indéfini vers sqrt [RESOLU]

De mémoire un flottant en mémoire contient un bit pour le signe, puis plusieurs bits pour l'exposant et enfin le reste pour la mantisse. Prendre la valeurs absolue se limite à forcer le bit du signe à 0 (0 : positif, -1:négatif)


PC fixe sous Bionic 64 bits et portable avec Focal 64 bits

Hors ligne

#15 Le 24/05/2017, à 21:10

grigouille

Re : reference indéfini vers sqrt [RESOLU]

plouf1221 a écrit :

Pour moi y a pas de problème la variable nbr_element est indépendante du systeme d'exploitation tout est proportionnel
si ton int est codé sur 4 octets et que tu as un tableau[4] => 16 octets en mémoire mais toujours 4 élements = 16 / 4
si ton int est codé sur 6 octets et que tu as un tableau[4] => 24 octets en mémoire mais toujours 4 élements = 24 / 6

Teste ton code avec ceci :

int main (int argc, char* argv[])              
 {
         double tableau[] = {-3.4, -5.6, 2., 2., 2., 2., 2.,2.,1.0  };
         printf ("%g", proche_zero (tableau));
 
         return EXIT_SUCCESS;
 }

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#16 Le 24/05/2017, à 21:47

JBF

Re : reference indéfini vers sqrt [RESOLU]

plouf1221 a écrit :

Merci une autre fonction dans la boutique cool

En faite je vais simplement remplacer sqrt (p[i] * p[i]) par fabs (p[i])

Et pourquoi pas directement :

fabs(tableau[i])

?


LibreOffice : https://fr.libreoffice.org/ (téléchargement, documentation, FAQ, assistance, contribuer, ...)
Aide pour LibreOffice par la communauté francophone : https://ask.libreoffice.org/fr/

Hors ligne

#17 Le 25/05/2017, à 12:27

eiger

Re : reference indéfini vers sqrt [RESOLU]

Salut,
Juste pour confirmer les doutes de grigouille : ta variable nbr_element ne contient pas ce que tu crois.

1. Ta fonction prend en argument un "double* tableau", soit un pointeur sur un double. À ce niveau, la fonction ne sait absolument pas qu'il s'agit d'un tableau.
Donc on va se retrouver avec sizeof(tableau) = [taille des pointeurs sur ta machine], ce qui comme le disait grigouille, dépend de ton processeur et de ton OS.
Si tu as une machine x86_64 avec un OS 64 bits par exemple, on aura probablement 8 octets.
Ensuite sizeof(*tableau) représente la taille de ce qui est pointé par tableau, à savoir un double, donc généralement 8 octets.
Conclusion: nbr_element vaut 1.

2. En C, la taille d'un tableau n'est pas incluse dans le tableau à l'exécution. Soit tu utilises effectivement un "array", par exemple double tableau[4] et le compilateur sait que tableau contient 4 éléments à la compilation uniquement, soit tu passes un pointeur, mais dans ce cas c'est à toi de toujours conserver la taille du tableau quelque part (par exemple dans une variable), et tu dois alors passer cette taille à toute fonction qui travaillerait
sur le tableau.

3. L'opérateur sizeof(...) est évalué à la compilation uniquement. Ce n'est pas une fonction appelée lors de l'exécution.

4. Quand on travaille avec des flottants (float ou double, peu importe), on évite les manipulations inutiles. Les types float ou double ne permettent pas de représenter toutes les valeurs et chaque calcul introduit des erreurs. Si en mathématiques sqrt(x*x) == x, ce ne sera pas forcément vrai en C, donc on évite. Comme quelqu'un l'a noté plus haut, a priori on peut supposer que la fonction fabs() se contentera de changer le bit de signe et sera donc plus "correcte".

5. Et sinon, on peut très bien faire cela en une seule passe sans allouer de mémoire:

double proche_zero(const double* tableau, const size_t nbr_element)
{
    double result=DBL_MAX;

    for (size_t i=0; i<nbr_element ; i++)
    {
        if (fabs(tableau[i]) < fabs(result))
            result = tableau[i];
    }

    return result;
}

Dernière modification par eiger (Le 25/05/2017, à 12:29)

Hors ligne

#18 Le 29/05/2017, à 15:51

plouf1221

Re : reference indéfini vers sqrt [RESOLU]

Pas le choix obliger de passer la taille du tableau en paramètre de la fonction en langage C avec un pointeur.
Par contre je ne comprends pas ce que fait ton code eiger, c'est quoi DBL_MAX ?
Merci pour toutes ces précisions.

Hors ligne

#19 Le 29/05/2017, à 19:59

eiger

Re : reference indéfini vers sqrt [RESOLU]

DBL_MAX, c'est la plus grande valeur représentable par une variable du type double.
Pour y accéder, il te faudra ajouter un

#include <float.h>

En gros l'idée c'était d'initialiser la variable "résultat" avec la plus grande valeur possible pour un double, en sachant que dès qu'une valeur plus petite est trouvée dans le tableau, elle est affectée à cette variable.
On peut initialiser "result" avec autre chose, par exemple la première valeur du tableau ... Mais dans ce cas, il faut tenir compte du cas particulier où on passe un tableau de taille nulle à la fonction. Et comme j'avais la flemme de rajouter cette condition, j'ai initialisé le résultat avec une valeur la plus grande possible. Du coup si le tableau est de taille nulle, tu obtiens DBL_MAX comme résultat.

Hors ligne

#20 Le 29/05/2017, à 21:20

grigouille

Re : reference indéfini vers sqrt [RESOLU]

Le cas du tableau vide doit être traité par un exit(EXIT_FAILURE).


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#21 Le 30/05/2017, à 13:00

plouf1221

Re : reference indéfini vers sqrt [RESOLU]

Ce qui nous donne en résumé :

La fonction proche_zero

double proche_zero (double* tableau, int taille)              
{
        double result = DBL_MAX;

        if (tableau == NULL)
        {
                printf ("Le tableau est de taille nul\n");
                exit (EXIT_FAILURE);
        }

        else
                for (unsigned int i = 0; i < taille; i++)
                        if (fabs (tableau[i]) < fabs (result))
                                result = tableau[i];

        return result;
}

Le main

int main (void)
{
        double array[] = { 1.0, 2.0, -0.4, -0.3, -0.03, -0.00000005, 0.00000000000006 };
        double* pointeur_double = array;

        printf ("%g\n", proche_zero (array, 7));
        printf ("%f\n", proche_zero (pointeur_double, 7));
}

Au niveau de l'affichage j'ai le retour suivant : 0.000000 et je ne comprends pas pourquoi. Il s'agit de double je ne pense pas avoir fait plus petit que la valeur la plus petite autorisé par un double sinon la précision est vraiment ridicule.

Hors ligne

#22 Le 30/05/2017, à 14:05

grigouille

Re : reference indéfini vers sqrt [RESOLU]

Extrait du man 3 printf :

f, F
L'argument réel, de type double, est arrondi, et présenté avec la notation classique [-]ccc.ccc, où le nombre de décimales est égal à la précision réclamée. Si la précision n'est pas indiquée, l'affichage se fera avec 6 décimales. Si la précision vaut zéro, aucun point n'est affiché. Lorsque le point est affiché, il y a toujours au moins un chiffre devant.

Après il y a d'autres problèmes dans ton programme.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne