Error en las medidas directas

prev.gif (997 bytes)chapter.gif (1105 bytes)home.gif (1232 bytes)next.gif (998 bytes)

Ejemplos completos

Planteamiento del problema

Diseño del applet

Una clase para el tratamiento de los datos

Conclusiones

El código fuente


Planteamiento del problema

Si al tratar de determinar una magnitud por medida directa realizamos varias medidas con el fin de corregir los errores aleatorios, y los resultados obtenidos son x1, x2, x3 ... xn, se adopta como mejor estimación del valor verdadero el valor medio <x> que viene dado por

De acuerdo con la teoría de Gauss de los errores, que supone que estos se producen por causas aleatorias, se toma como la mejor estimación del error, para el valor experimental, obtenido como valor medio de un conjunto n de medidas, el llamado error cuadrático D x definido por

El resultado del experimento se expresa como <x>± D x

 

Diseño del applet

En primer lugar, hemos de pensar en identificar y separar, los distintos elementos que entran en un proyecto, en este caso, el interfaz o medio de comunicación entre el usuario y el programa, y el procedimiento de tratamiento de los datos.

Nuestro proyecto consistirá básicamente en dos archivos: el primero describirá el interfaz mediante una clase derivada (o subclase) de la clase Applet. Y el segundo, describirá el procedimiento numérico mediante una clase que denominaremos Error.

 

Disposición de los componentes en el applet

Antes de decidir qué controles se van a utilizar y su disposición en la ventana del applet, hemos de pensar cómo va a ser la interacción entre el usuario y el programa. En primer lugar, introducirá los datos, a continuación pulsará un botón, y finalmente, aparecerán los resultados (la medida y el error).

En el applet, se muestra la disposición de los controles, a la izquierda el control área de texto, a la derecha los controles de edición y los botones titulados Calcular y Borrar.

Hay muchas maneras de disponer los controles, de acuerdo con el gusto personal y la experiencia del programador. En este caso, hemos dividido la ventana del applet en dos partes, la parte izquierda la ocupa el control área de texto tDatos , y la parte derecha un panel Panel1 que contiene al resto de los controles. Se ha empleado GridLayout como gestor de diseño para estos dos componentes.

   this.setLayout(gridLayout1);
   this.add(tDatos, null);
   this.add(Panel1, null);

Para disponer el resto de los controles sobre el Panel1, se ha empleado el gestor de diseño GridBagLayoutSe crean dos objetos, uno gbc1 de la clase GridBagConstraints, y otro gbl1 de la clase GridBagLayout

  GridBagLayout gbl1 = new GridBagLayout();
  GridBagConstraints gbc1=new GridBagConstraints();

Se establece el gestor de diseño para este panel, mediante la función miembro setLayout

  Panel1.setLayout(gbl1);

A continuación, se sitúan los controles sobre dicho panel, utilizando las distintas propiedades (constraints) que definen este complicado gestor de diseño.

//panel 1
//primera fila
     Panel1.setLayout(gbl1);
     gbc1.anchor=GridBagConstraints.WEST;
     gbc1.gridwidth=1;
     gbc1.insets=new Insets(5,0,5,0);
     Panel1.add(label1, gbc1);
     gbc1.gridwidth=GridBagConstraints.REMAINDER;
     Panel1.add(tMedio, gbc1);

//segunda fila
     gbc1.anchor=GridBagConstraints.WEST;
     gbc1.gridwidth=1;
     gbc1.insets=new Insets(5,0,5,0);
     Panel1.add(label2, gbc1);
     gbc1.gridwidth=GridBagConstraints.REMAINDER;
     Panel1.add(tError, gbc1);

//tercera fila
     gbc1.anchor=GridBagConstraints.CENTER;
     gbc1.gridwidth=1;
     gbc1.insets=new Insets(25,0,5,0);
     Panel1.add(btnCalcular, gbc1);
     gbc1.gridwidth=GridBagConstraints.REMAINDER;
     Panel1.add(btnBorrar, gbc1);

En los controles de edición tMedio y tError se muestran los resultados del cálculo, por lo que no precisan ser editados o modificados por el usuario, para ello se pone su propiedad Editable en false.

  tMedio.setEditable(false);

Respuesta a las acciones del usuario.

Una vez que se ha diseñado el interfaz, se definen las funciones respuesta a las acciones del usuario sobre los botones. Para cada uno de los botones se crea un objeto de una clase anónima interna que maneja las acciones del usuario sobre cada botón.

    btnCalcular.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        btnCalcular_actionPerformed(e);
      }
    });

A continuación, se define la función respuesta btnCalcular_actionPerformed que realiza varias tareas:

  1. Lee los datos que se han introducido en el control área de texto tDatos,
    String entrada=tDatos.getText();
  1. Crea el objeto error de la clase Error e inicializa sus miembros dato.
    Error error=new Error();
    error.setDatos(entrada);
  1. Llama desde este objeto a la función miembro calcular que calcula el valor medio y el error absoluto.
    error.calcular();
  1. Muestra los resultados del cálculo en los controles de edición tMedio y tError, para ello, se formatean los resultados mostrándose hasta con 4 decimales mediante la función Math.round, y se convierten los números decimales en su representación textual, objetos de la clase String. La función Math.round devuelve un entero que se ha de promocionar a un double (casting), para poder efectuar la división.
(double)Math.round(error.valorMedio*10000)/10000;

Alternativamente, se podría emplear la función Math.floor que devuelve un double

Math.floor(error.media*10000)/10000; 

La diferencia estriba en que Math.floor expresa el número 0.45638021, tomando cuatro cifras decimales como 0.4563, mientras que empleando la función Math.round se obtiene una mejor aproximación de la última cifra 0.4564 como cabría esperar.

 

Una clase para el tratamiento de los datos

Denominaremos Error a la clase que emplearemos para realizar el tratamiento de los datos. Dicha clase tendrá como miembros, el número n de datos que se va a tratar, un array x que guardará dichos datos numéricos, y finalmente, dos miembros que guardarán los resultados denominados valorMedio y errorAbsoluto.

La función miembro setDatos, inicializa el array x, y la función miembro calcular realiza el cálculo del valor medio y del error absoluto de acuerdo con las fórmulas mencionadas en el primer apartado.

Los datos se introducen en el control área de texto tDatos. Leemos los datos introducidos mediante la función getText que devuelve un string. La inicialización del array x se realiza a través del objeto de la clase String que se le pasa a la función miembro setDatos.

La clase StringTokenizer nos rompe el texto extraído del control área de texto en trozos (tokens) que se guardan en el string local subTexto, representando cada trozo un dato que hemos introducido. El separador, un retorno de carro, se introduce en el segundo argumento de su constructor.

public class Error {
//otros miembros...	
   boolean setDatos(String texto){
	StringTokenizer t=new StringTokenizer(texto,"\n");
	n=t.countTokens();
	if (n<3)  return false;
	x=new double[n];
	int i=0;
	while(t.hasMoreTokens()){
		String subTexto=(String)t.nextToken();
		x[i]=Double.valueOf(subTexto.trim()).doubleValue();
		i++;
	}
	return true;
   }
}

 

La medida y el error

Una vez creado e inicializado el array x. La función miembro calcular no reviste dificultad alguna, ya que para definirla basta traducir las fórmulas matemáticas a código.

public class Error {
   //otros miembros... 
   void calcular(){
	valorMedio=0.0;
	for(int i=0; i<n; i++){
		valorMedio+=x[i]/n;
	}
	double desviacion=0.0;
	for(int i=0; i<n; i++){
		desviacion+=(x[i]-valorMedio)*(x[i]-valorMedio);
	}
	errorAbsoluto=Math.sqrt(desviacion/(n*(n-1)));
   }
}

Los miembros dato valorMedio y errorAbsoluto, guardan los resultados. Para que los valores que guardan sean conocidos desde la clase que describe el applet, se pueden emplear dos alternativas, definir dos funciones miembro getMedia y getError, que devuelvan dichos datos o bien, no declarar privados (private) a los miembros dato valorMedio y errorAbsoluto

	error.valorMedio;
	error.getMedia();

La segunda opción, está de acuerdo con el espíritu de la Programación Orientada a Objetos, una de cuyas características básicas es la encapsulación, que trata de restringir en lo posible el acceso a la información que guardan los objetos de dicha clase mediante ciertos modificadores denominados private, protected, public o default (cuando no se pone modificador).

 

Conclusiones

Varios son los aspectos de la programación Java tratados en este capítulo, entre los que cabe destacar

 

El código fuente

disco.gif (1035 bytes)error: ErrorApplet.java, Error.java