Creando una función para hallar la media y la desviación

Iniciado por Schrödinger, 13 Mayo 2013, 19:24 PM

0 Miembros y 1 Visitante están viendo este tema.

Schrödinger

Quiero hacer un programa que genere N floats uniformemente distribuidos en un intervalo dado y que calcule la media y la dispersión mediante una función. El código es el siguiente:


#include <stdio.h>
#include <stdlib.h>
#define DEBUG
int N;
FILE *fout;

void med_var(float *serie, int Numero, float *Media, float *Varianza)
{
  int i;
  for(i=0;i<Numero;i++)
    {
      *Media+=serie[i];
    }
  *Media=*Media/Numero;
  for(i=0;i<Numero;i++)
    {
      *Varianza+=serie[i]*serie[i];
    }
  *Varianza=*Varianza/Numero;
  *Varianza=*Varianza-(*Media)*(*Media);
  printf("Media=%f, Varianza=%f\n",*Media,*Varianza);
}

float frandom(double min, double max)
{
  return min+(max-min)*(rand()/((double)RAND_MAX+1));
}

main(argc,argv)
int argc;
char **argv;
{
  switch(argc)
    {
    case 2:
      sscanf(argv[1],"%d",&N);
      break;
    default:
      N=100;
    }
  int i;
  float med,var,data[N];

  printf("%d\n",N);
 
  fout=fopen("datos.dat","wt");

  for(i=0;i<N;i++)
    {
      data[i]=frandom(-2,5);
    }

#ifdef DEBUG
  for(i=0;i<N;i++)
    {
      printf("data[%d]=%f\n",i,data[i]);
    }
#endif

  med_var(data,N,&med,&var);

  fprintf(fout,"\n%d %f %f",N,med,var);
  fclose(fout);
}


Compila sin problemas pero los valores para la media y la varianza son incorrectos. El caso es que en una versión anterior del programa en la cual N no estaba pillado de la consola al menos la media funcionaba.

¿Alguna pista?

rir3760

El problema se debe a la declaración de la variable "data":
int N;

/* ... */

float med,var,data[N];

Un array declarado en esa forma se conoce como array de longitud variable o VLA, los dolores de cabeza surgen por el soporte variado de estos en los distintos estándares de C:

A) En C90 los VLAs no son validos.
B) En C99 los VLAs son validos.
C) En C11 los VLAs son validos pero su soporte es opcional.

Para que el programa funcione correctamente debes verificar que tu compilador soporte el estándar C99 (y por supuesto que se compile en ese modo).

Por ello es mejor, en mi opinión, reservar memoria de forma dinámica. Mas o menos así:
int N;

/* ... */

/* 1) Declaracion del puntero */
float med,var,*data;

/* 2) Reserva de memoria */
data = malloc(N * sizeof *data);

/* ... */

/* Cuando ya no sea necesaria la memoria se libera */
free(data);


Por ultimo tienes que cambiar la definicion de la funcion main.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

leosansan

#2
Cita de: Schrödinger en 13 Mayo 2013, 19:24 PM
Quiero hacer un programa que genere N floats uniformemente distribuidos en un intervalo dado y que calcule la media y la dispersión mediante una función
...............................................................

Compila sin problemas pero los valores para la media y la varianza son incorrectos. El caso es que en una versión anterior del programa en la cual N no estaba pillado de la consola al menos la media funcionaba.

¿Alguna pista?

El problema radica, con permiso de rir, en que no inicializas las  variables *media=0 y *varianza=0 antes de los correspondientes for. A mí, con esta pequeñísima corrección, me ha funcionado bien, creo.

Saluditos!. ......  

rir3760

Cita de: leosansan en 14 Mayo 2013, 15:41 PM
El problema radica, con permiso de rir, en que no inicializar las  variables *media=0 y *varianza=0 antes de los correspondientes for.
Tienes razón, no era un problema sino dos (el uso del VLA y las dos variables sin inicializar).

¿O son tres? Lo menciono porque:

1) Debido a que la definición de la función main omite el tipo de retorno no se puede compilar como C99 (no seria valido).

2) La declaración del array "data" requiere compilar como C99.

...

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

leosansan

Cita de: rir3760 en 14 Mayo 2013, 16:50 PM
Tienes razón, no era un problema sino dos (el uso del VLA y las dos variables sin inicializar).

¿O son tres? Lo menciono porque:

1) Debido a que la definición de la función main omite el tipo de retorno no se puede compilar como C99 (no seria valido).

2) La declaración del array "data" requiere compilar como C99.

...


Ya sé que main debería ser declarado como int y que el uso de VLAs da problemas al no estar implementado en algunos compiladores, sin embargo en ese caso lo mejor es cambiar de compilador a uno más "funcional". En mi caso con Code::Blocks no he tenido problema alguno ni con main ni con los VLAs, que utilizo frecuentemente sin problemas.

Vamos que si el compilador "no tira" por falta de implementación de ciertas funcionalidades del C99 sencillamente cambiaría de compilador.

Saluditos!. .....