Annuncio

Collapse
No announcement yet.

Programmare in C

Collapse
X
 
  • Filter
  • Ora
  • Show
Clear All
new posts

    Programmare in C

    Qualcuno di voi se ne intende un po? Io qualcosina so, ma le mie domande vanno al di là della mia conoscenza.
    Avrei una domandina...
    To failure
    sigpic

    Diario
    http://www.bodyweb.com/forums/blogs-...ml#post5990915


    #2
    Non essere timido, dicci tutto.
    Always the beautiful answer who asks a more beautiful question

    Commenta


      #3
      Dica pure
      Ingegnere88

      Commenta


        #4
        Originariamente Scritto da 600 Visualizza Messaggio
        Non essere timido, dicci tutto.
        Sono uno statistico e uso R. R è un programma basato su C e Fortran ed è di più alto livello rispetto a questi ultimi. Quindi certe operazioni sono più lente (tipo i loops) e quindi può risultare conveniente portare parti di codice R in C e poi richiamare la libreria dinamica da R.
        In sostanza vi faccio questo esempio

        #include<stdio.h>
        #include<math.h>

        static int work( int number, int (*function)(int, ...) )
        {
        int i, j;

        for ( i = j = 0; i < number; i++ )
        j += ( *function )( i, i );

        return(j);
        }

        /* questa è la funzione che chiameremo in work */

        static int bustra(int a, int b)
        {
        return(a+pow(b,2));
        }

        /* wrapper per R */
        void chiamata(int *res, int *b)
        {
        *res=work(*b,bustra);
        }

        /*
        # In R
        dyn.load("bustra_function_calls.so")

        chiamata<-function(a)
        {
        .C("chiamata",as.integer(0),as.integer(a))
        }
        chiamata(1)
        */

        Il bello è che, come in R, si possono avere funzioni o puntatori a funzioni con numero variabile di argomenti. Il fatto è che io vorrei un modo per passare gli argomenti opzionali non a mano come fatto in ( *function )( i, i );. Infatti le funzioni utilizzate non hanno sempre tutti gli argomenti dello stesso tipo (si posso avere per esempio static int bustra(int a, int b, double c)) e quindi non ho ben capito se passare una lista di argomenti (con va_list) sia la soluzione adatta visto che ti vincola ad avere argomenti dello stesso tipo. Inoltre dagli esempi che ho visto in giro non ho ben capito come funziona

        Grazie!
        To failure
        sigpic

        Diario
        http://www.bodyweb.com/forums/blogs-...ml#post5990915

        Commenta


          #5
          allora se ho capito bene ti serve una funzione che porti con se un numero variabile di argomenti.
          In C dev intanto includere la libreria "stdarg.h".
          Allora normalmente nei casi più semplici devono essere dello stesso tipo, però utilizzando le macro in particolare "type va_arg", puoi gestire anche parametri diversi per "tipo"

          -va_list ap;
          gli oggetti di tipo va_list contengono le informazioni necessarie a lavorare con un numero variabile di argomenti.
          -void va_start(va_list ap, argNum);
          è una macro che inizializza l'oggetto di tipo va_list in modo che possa essere utilizzato da va_arg e va_end; deve essere chiamata prima che si tenti di accedere agli argomenti di un elenco variabile.
          -type va_arg(va_list ap, tipo);
          è una macro che viene espansa in un'espressione che ha il valore e il tipo dell'argomento successivo di un elenco variabile di argomenti e deve essere chiamata un numero di volte uguale al numero degli argomenti; modifica l'oggetto dichiarato va_list in modo che punti al prossimo argomento dell'elenco. Il tipo deve essere il tipo dell'argomento.
          -void va_end(va_list ap);
          è una macro chiamata quando tutti gli elementi di un elenco variabile di argomenti, che era stato inizializzato dalla macro va_start, sono stati elaborati; fa in modo che la restituzione del controllo della funzione sia corretta.
          Ingegnere88

          Commenta


            #6
            Originariamente Scritto da Ingegnere88 Visualizza Messaggio
            allora se ho capito bene ti serve una funzione che porti con se un numero variabile di argomenti.
            In C dev intanto includere la libreria "stdarg.h".
            Allora normalmente nei casi più semplici devono essere dello stesso tipo, però utilizzando le macro in particolare "type va_arg", puoi gestire anche parametri diversi per "tipo"

            -va_list ap;
            gli oggetti di tipo va_list contengono le informazioni necessarie a lavorare con un numero variabile di argomenti.
            -void va_start(va_list ap, argNum);
            è una macro che inizializza l'oggetto di tipo va_list in modo che possa essere utilizzato da va_arg e va_end; deve essere chiamata prima che si tenti di accedere agli argomenti di un elenco variabile.
            -type va_arg(va_list ap, tipo);
            è una macro che viene espansa in un'espressione che ha il valore e il tipo dell'argomento successivo di un elenco variabile di argomenti e deve essere chiamata un numero di volte uguale al numero degli argomenti; modifica l'oggetto dichiarato va_list in modo che punti al prossimo argomento dell'elenco. Il tipo deve essere il tipo dell'argomento.
            -void va_end(va_list ap);
            è una macro chiamata quando tutti gli elementi di un elenco variabile di argomenti, che era stato inizializzato dalla macro va_start, sono stati elaborati; fa in modo che la restituzione del controllo della funzione sia corretta.
            grazie delle nozioni, che avevo già letto ma non così chiare!!! ti allego un esempio concreto per vedere se con l'esempio anche uno statistico ci arriva:

            static int work( int number, int (*function)(double x, ...) )
            {
            ( *function )( x,???);
            }

            static double parabola(double x, double *data, int length_data)
            {
            int i;
            double res;
            for(i=0;i<length_data;i++)
            {
            res+= data[i]*pow(x,2);
            }
            return(res);
            }
            come faresti a passare in work gli argomenti, in questo caso specifico, di parabola? cioè data punta a un vettore di double e length_data è il numero di elementi...ti farò un monumento
            To failure
            sigpic

            Diario
            http://www.bodyweb.com/forums/blogs-...ml#post5990915

            Commenta


              #7
              ot: questi vengono da un altro pianeta XD
              - Climber
              - ex Istruttore
              - ex P.Trainer AFFWA

              Commenta


                #8
                Originariamente Scritto da NL84 Visualizza Messaggio
                grazie delle nozioni, che avevo già letto ma non così chiare!!! ti allego un esempio concreto per vedere se con l'esempio anche uno statistico ci arriva:

                static int work( int number, int (*function)(double x, ...) )
                {
                ( *function )( x,???);
                }

                static double parabola(double x, double *data, int length_data)
                {
                int i;
                double res;
                for(i=0;i<length_data;i++)
                {
                res+= data[i]*pow(x,2);
                }
                return(res);
                }
                come faresti a passare in work gli argomenti, in questo caso specifico, di parabola? cioè data punta a un vettore di double e length_data è il numero di elementi...ti farò un monumento
                allora scusami intanto per averti risp solo ora. Ma nn ho avuto tempo. Ho fatto qualke ricerca ed in pratica ho avuto la conferma che col C devi necessariamente sapere già a priori il tipo di variabili che utilizzi, in quanto quando vai a richiamanre la macro "type va_arg(va_list ap, tipo)"
                devi richiamarla ogni qualvolta c'è un cambiamento di tipo dei paramentri, infatti cm ti scrissi sopra:
                " deve essere chiamata un numero di volte uguale al numero degli argomenti; modifica l'oggetto dichiarato va_list in modo che punti al prossimo argomento dell'elenco. Il tipo deve essere il tipo dell'argomento
                esempio:

                int somma(int argNum, ...){
                int totale = 0;

                va_list ap;
                va_start(ap, argNum);
                while(argNum--)
                totale += va_arg(ap, int);

                va_end(ap);
                ------------------------------

                Se vuoi cambiare il tipo fari una cosa del genere
                int somma(int argNum, ...){
                int totale = 0;

                ap;
                va_start(ap, argNum);
                while(argNum--)
                totale += va_arg(ap, int);
                .....
                ......
                ....

                /*ecco poi una cosa del genere cambi il tipo, ma cm vedi devi saperlo già a priori*/

                type va_arg(va_list ap, CHAR )
                ....
                ....

                va_end(ap);
                -----




                Originariamente Scritto da X3me Visualizza Messaggio
                ot: questi vengono da un altro pianeta XD

                Ingegnere88

                Commenta


                  #9
                  Originariamente Scritto da Ingegnere88 Visualizza Messaggio
                  allora scusami intanto per averti risp solo ora. Ma nn ho avuto tempo. Ho fatto qualke ricerca ed in pratica ho avuto la conferma che col C devi necessariamente sapere già a priori il tipo di variabili che utilizzi, in quanto quando vai a richiamanre la macro "type va_arg(va_list ap, tipo)"
                  devi richiamarla ogni qualvolta c'è un cambiamento di tipo dei paramentri, infatti cm ti scrissi sopra:
                  " deve essere chiamata un numero di volte uguale al numero degli argomenti; modifica l'oggetto dichiarato va_list in modo che punti al prossimo argomento dell'elenco. Il tipo deve essere il tipo dell'argomento
                  esempio:

                  int somma(int argNum, ...){
                  int totale = 0;

                  va_list ap;
                  va_start(ap, argNum);
                  while(argNum--)
                  totale += va_arg(ap, int);

                  va_end(ap);
                  ------------------------------

                  Se vuoi cambiare il tipo fari una cosa del genere
                  int somma(int argNum, ...){
                  int totale = 0;

                  ap;
                  va_start(ap, argNum);
                  while(argNum--)
                  totale += va_arg(ap, int);
                  .....
                  ......
                  ....

                  /*ecco poi una cosa del genere cambi il tipo, ma cm vedi devi saperlo già a priori*/

                  type va_arg(va_list ap, CHAR )
                  ....
                  ....

                  va_end(ap);
                  -----







                  Chiaramente scusami per non averti più risposto ma non ho avuto la possibilità di avere una connessione (nel 2010!!!). Ho risolto con le strutture: cioè specifico un certo tipo di struttura per gli argomenti "opzionali" (in base all'ordine di comparsa nella funzione) della funzione e il gioco è fatto
                  To failure
                  sigpic

                  Diario
                  http://www.bodyweb.com/forums/blogs-...ml#post5990915

                  Commenta


                    #10
                    ottimo, posta qualkosa se ti va, può essere sempre utile
                    Ingegnere88

                    Commenta


                      #11
                      ecco qui. Funzione Bustra_R_zeroin permette di trovare gli zeri di una funzione. Il vantaggio che ho trovato nell'usare la struttura è che in questo modo devo solo cambiare la dichiarazione e aggiungere 2 righe di codice (all'inizio) invece che cambiare gli argomenti di f() all'interno della routine di ottimizzazione. Devo dire che la gestione dell'errore fa cacare e dovrò darmi una regolata :-)

                      #include <float.h>
                      #include <math.h>
                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <errno.h>



                      #define EPSILON DBL_EPSILON



                      static double parabola(double x, double *data, int length_data)
                      {
                      int i;
                      double res;
                      for(i=0;i<length_data;i++)
                      {
                      res+= data[i]*pow(x,2)-2;
                      }
                      return(res);
                      }

                      /* dichiarare nella struttura gli argomenti della propria funzione (quelli che vengono dopo il parametro). Rispettare l'ordine concui sono riportati nella propria funzione e stare attenti se si sono dichiarati puntatori!*/

                      struct arguments_strucure{
                      double *data;
                      int length_data;
                      } arguments;


                      double Bustra_R_zeroin( /* An estimate of the root */
                      double *ax1, /* Left border | of the range */
                      double *bx1, /* Right border| the root is seeked*/
                      double *Tol, /* Acceptable tolerance */
                      int *Maxit, /* Max # of iterations */
                      double (*f)(double, ...), /* Function under investigation */
                      double *data, /* Other arguments for f*/
                      int *length_data )

                      {
                      /* argomenti della funzione */
                      arguments.data=&data[0];
                      arguments.length_data=*length_data;

                      double ax, bx;
                      ax=*ax1;
                      bx=*bx1;

                      double a,b,c, /* Abscissae, descr. see above */
                      fa, fb, fc; /* f(a), f(b), f(c) */
                      double tol;
                      int maxit;

                      a = ax; b = bx;
                      fa = (*f)(a, arguments);
                      fb = (*f)(b, arguments);
                      c = a; fc = fa;
                      maxit = *Maxit + 1; tol = * Tol;

                      if( (fa>0 && fb<0) || (fa<0 && fb>0) )
                      {

                      while(maxit--) /* Main iteration loop */
                      {
                      double prev_step = b-a; /* Distance from the last but one
                      to the last approximation */
                      double tol_act; /* Actual tolerance */
                      double p; /* Interpolation step is calcu- */
                      double q; /* lated in the form p/q; divi-
                      * sion operations is delayed
                      * until the last moment */
                      double new_step; /* Step at this iteration */

                      if( fabs(fc) < fabs(fb) )
                      { /* Swap data for b to be the */
                      a = b; b = c; c = a; /* best approximation */
                      fa=fb; fb=fc; fc=fa;
                      }
                      tol_act = 2*EPSILON*fabs(b) + tol/2;
                      new_step = (c-b)/2;

                      if( fabs(new_step) <= tol_act || fb == (double)0 )
                      {
                      *Maxit -= maxit;
                      *Tol = fabs(c-b);
                      return b; /* Acceptable approx. is found */
                      }

                      /* Decide if the interpolation can be tried */
                      if( fabs(prev_step) >= tol_act /* If prev_step was large enough*/
                      && fabs(fa) > fabs(fb) ) { /* and was in true direction,
                      * Interpolation may be tried */
                      register double t1,cb,t2;
                      cb = c-b;
                      if( a==c ) { /* If we have only two distinct */
                      /* points linear interpolation */
                      t1 = fb/fa; /* can only be applied */
                      p = cb*t1;
                      q = 1.0 - t1;
                      }
                      else { /* Quadric inverse interpolation*/

                      q = fa/fc; t1 = fb/fc; t2 = fb/fa;
                      p = t2 * ( cb*q*(q-t1) - (b-a)*(t1-1.0) );
                      q = (q-1.0) * (t1-1.0) * (t2-1.0);
                      }
                      if( p>(double)0 ) /* p was calculated with the op-*/
                      q = -q; /* posite sign; make p positive */
                      else /* and assign possible minus to */
                      p = -p; /* q */

                      if( p < (0.75*cb*q-fabs(tol_act*q)/2) /* If b+p/q falls in [b,c]*/
                      && p < fabs(prev_step*q/2) ) /* and isn't too large */
                      new_step = p/q; /* it is accepted
                      * If p/q is too large then the
                      * bisection procedure can
                      * reduce [b,c] range to more
                      * extent */
                      }

                      if( fabs(new_step) < tol_act) { /* Adjust the step to be not less*/
                      if( new_step > (double)0 ) /* than tolerance */
                      new_step = tol_act;
                      else
                      new_step = -tol_act;
                      }
                      a = b; fa = fb; /* Save the previous approx. */
                      b += new_step;
                      fb = (*f)(b, arguments); /* Do step to a new approxim. */
                      if( (fb > 0 && fc > 0) || (fb < 0 && fc < 0) ) {
                      /* Adjust c for it to have a sign opposite to that of b */
                      c = a; fc = fa;
                      }

                      }
                      }
                      /* failed! */
                      *Tol = fabs(c-b);
                      perror("Error:\nf() values at end points not of opposite sign");
                      return 1e6;
                      }


                      /* Wrapper per R */

                      void zero_finding(double *res, double *ax1, double *bx1, double *Tol, int *Maxit, double *data, int *length_data )
                      {
                      *res=Bustra_R_zeroin( ax1, bx1, Tol, Maxit, parabola, data, length_data);
                      }

                      #if 0

                      dyn.load("bustra_zeroin_structure.so")
                      zero_finder<-function(a,b,data)
                      {
                      .C("zero_finding",as.double(0),as.double(a),as.double(b),as.double(1e-8),as.integer(1e2),as.double(data),as.integer(length(data)))[[1]]
                      }

                      #ok
                      zero_finder(-2,0,1:10)
                      #errore
                      zero_finder(-2,2,1:10)

                      #in R
                      funz<-function(x,data)
                      {
                      sum(data*x^2-2)
                      }

                      uniroot(f=funz,int=c(-2,2),data=1:10)

                      #confronto
                      system.time(for(i in 1:1e4) zero_finder(-2,0,1:10))
                      user system elapsed
                      0.160 0.000 0.159


                      system.time(for(i in 1:1e4) uniroot(f=funz,int=c(-2,0),data=1:10))
                      user system elapsed
                      0.904 0.000 0.904

                      #la funzione funz è molto lenta rispetto a quella in C. Verificare con Rprof.



                      #endif
                      To failure
                      sigpic

                      Diario
                      http://www.bodyweb.com/forums/blogs-...ml#post5990915

                      Commenta


                        #12


                        Segnalato per linguaggio non conforme
                        Originariamente Scritto da Pesca
                        lei ti parla però, ti saluta, è gentile, sei tu la merda hunt

                        Commenta


                          #13
                          Ingegnere88

                          Commenta


                            #14
                            Originariamente Scritto da Naturalissimo.88 Visualizza Messaggio


                            Segnalato per linguaggio non conforme
                            Non capisco
                            To failure
                            sigpic

                            Diario
                            http://www.bodyweb.com/forums/blogs-...ml#post5990915

                            Commenta


                              #15
                              niente era una battua, intendeva che ti ha segnalato allo staff poichè non stavamo scrivendo in linguaggio comprensibile..ma era una semplice battuta
                              Ingegnere88

                              Commenta

                              Working...
                              X
                              😀
                              🥰
                              🤢
                              😎
                              😡
                              👍
                              👎