[ Foro de C ]

Duda con ejercicio tema 9

26-Jul-2012 21:42
Antonio Rodriguez
9 Respuestas

Hola Nacho!

Estoy empezando el tema 9, concretamente he llegado al primer ejercicio en la pagina 135:

Crear una función que calcule las dos soluciones de una ecuación de segundo grado ax2 + bx + c = 0 y devuelva las dos soluciones como parámetros.

Lo he planteado de la siguiente forma:

1º Pregunto al usuario los valores de a, b y c y los asigno a tres variables.

2º Traspaso los valores a una función llamada "cuadratica" pasando los parámetros por referencia (creo que no sería necesario hacerlo así, pero lo he hecho por practicar el método)

3º En la función cuadrática pueden darse tres casos, dependiendo del resultado del discriminante (b2-4*a*c): si es mayor que 0 la ecuación tiene dos soluciones distintas, si es igual a 0 tiene una solución y si es menor que 0 la ecuación no tiene soluciones reales.

El problema es cómo devuelvo estas posibles soluciones a la función principal. He pensado en almacenar la solución en una variable (o dos) y devolver a la función principal la dirección de esa variable, pero me encuentro con varios problemas: Sé devolver la dirección de una variable, pero no sé cómo usarla desde la función principal. Además, en el caso de dos soluciones (dos variables) no sabría cómo devolver la dirección de las dos variables. Para terminar, en el caso de que la ecuación no tenga solución real, lo ideal sería devolver una cadena diciendo que no tiene solución, cosa que tampoco veo cómo hacer.

En fin, que estoy un poco perdido, a ver si puedes orientarme.

Un saludo!


26-Jul-2012 23:14
Nacho Cabanes (+83)

La única forma (razonable) de devolver dos valores de una función es usando parámetros por referencia. Por tanto, a, b y c no necesitan ser parámetros por referencia, pero x1 y x2 sí deben serlo.


27-Jul-2012 02:08
Antonio Rodriguez

Bueno, he seguido intentándolo y lo que se dice funcionar, funciona. Lo que no sé es si es lo que pretendías con el ejercicio, lo pongo por si tienes algún comentario:


/* Ejercicio 9.1
Crear una funcion que calcule las dos soluciones de una ecuacion de segundo grado
(Ax2+bx+c=0) y devuelva las dos soluciones como parametros*/

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

void cuadratica(float a, float b, float c, float *x1, float *x2, int *control) {
	float discriminante;
	discriminante=((b * b)-(4 * a * c));
	/*Si el discriminante es mayor que cero, la ecuación tiene dos soluciones, con números reales distintos*/
	if (discriminante>0) { 
			*x1=((-1) * b + sqrt(discriminante))/(2 * a);
			*x2=((-1) * b - sqrt(discriminante))/(2 * a);
			*control=1;
			}			
	/*Si el discriminante es igual a cero, la ecuación tiene una solución doble*/
	if (discriminante==0) {
			*x1=(((-1) * b)/(2 * a));
			*x2=(((-1) * b)/(2 * a));
			*control=2;
			}
			
	/*Si el discriminante es menor que cero, la ecuación no tiene soluciones reales*/		
	if (discriminante<0) {
			*control=3;
			}	

		}

main() {
	float x, y, z, x1, x2;
	int control=0; /* La usaremos para saber que tipo de ecuacion es*/ 
	
	printf("Introduce el valor de a: ");
	scanf("%f", &x);
	getchar();
	printf("Introduce el valor de b: ");
	scanf("%f", &y);
	getchar();
	printf("Introduce el valor de c: ");
	scanf("%f", &z);
	getchar();
	
	cuadratica(x, y, z, &x1, &x2, &control);
	
	if (control==1) 	printf("La ecuacion tiene dos soluciones reales: %0.4f y %0.4f", x1, x2);
	if (control==2) 	printf("La ecuacion tiene una solucion doble: %0.4f y %0.4f", x1, x2);
	if (control==3) 	printf("La ecuacion no tiene soluciones reales");
	return 0;
}



Saludos!


27-Jul-2012 11:59
Nacho Cabanes (+83)

La pinta es buena. Por legibilidad, no necesitas llamar X, Y, Z a los valores que pides al usuario: se pueden llamar también a, b, c, porque están en un ámbito distinto.

Otra alternativa es no devolver la variable "control", sino valores "absurdos" para x1 y x2 cuando no existe alguna de las soluciones, o incluso devolver valores como esos, pero como valor de retorno de la función, no como parámetro por referencia.


27-Jul-2012 12:29
Antonio Rodriguez

Gracias Nacho.

Los punteros es un tema complicado, ya que cambia totalmente la perspectiva desde donde veíamos las variables, pero de momento la explicación es muy meticulosa y se entiende bien.

Un saludo!


27-Jul-2012 16:42
Antonio Rodriguez

Siguiendo las indicaciones de Nacho, propongo otra versión: ahora cuando la solución no existe se le asigna a la variable un valor "absurdo" (en este caso 'w')


/* Ejercicio 9.1
Crear una funcion que calcule las dos soluciones de una ecuacion de segundo grado
(Ax2+bx+c=0) y devuelva las dos soluciones como parametros*/

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

void cuadratica(float a, float b, float c, float *x1, float *x2) {
	float discriminante;
	discriminante=((b * b)-(4 * a * c));
	/*Si el discriminante es mayor que cero, la ecuación tiene dos soluciones, con números reales distintos*/
	if (discriminante>0) { 
			*x1=((-1) * b + sqrt(discriminante))/(2 * a);
			*x2=((-1) * b - sqrt(discriminante))/(2 * a);
			}			
	/*Si el discriminante es igual a cero, la ecuación tiene una solución doble*/
	if (discriminante==0) {
			*x1=(((-1) * b)/(2 * a));
			*x2='w'; /* Valor "absurdo" cuando la solución no existe*/
			}
			
	/*Si el discriminante es menor que cero, la ecuación no tiene soluciones reales*/		
	if (discriminante<0) {
			*x1='w'; /* Valor "absurdo" cuando la solución no existe*/
			*x2='w'; /* Valor "absurdo" cuando la solución no existe*/
			}	

		}

main() {
	float a, b, c, x1, x2;
	
	printf("Introduce el valor de a: ");
	scanf("%f", &a);
	getchar();
	printf("Introduce el valor de b: ");
	scanf("%f", &b);
	getchar();
	printf("Introduce el valor de c: ");
	scanf("%f", &c);
	getchar();
	
	cuadratica(a, b, c, &x1, &x2);
	
	if ((x1!='w')&&(x2!='w')) 	printf("La ecuacion tiene dos soluciones reales: %0.4f y %0.4f", x1, x2);
	if ((x1!='w')&&(x2=='w')) 	printf("La ecuacion tiene una solucion doble: %0.4f", x1);
	if ((x1=='w')&&(x2=='w')) 	printf("La ecuacion no tiene soluciones reales");
	return 0;
}



28-Jul-2012 11:31
Nacho Cabanes (+83)

Esa solución es buena, Antonio. Aun así, eso de dar un valor que sea una letra para un dato numérico, aunque C lo permite, tiene dos problemas:

- Es antinatural. Si es dato es un número, que tenga un valor numérico.

- Puede ser que el resultado sea "menos raro" de lo que esperas. Por ejemplo, la letra "w" tiene el código ASCII 119, que, aun siendo un valor poco habitual para el resultado de una ecuación de segundo grado, es una valor posible.

Puedes hacer algo como x1 = -9999 o x1 = 1234,56, que, siendo datos igual de "poco probables" (o más), son claramente numéricos.


28-Jul-2012 13:39
Antonio Rodriguez

Tienes razón Nacho, tampoco me convencía la opción de asignar una letra a un dato numérico. Lo hice por evitar en la medida de lo posible números, ya que aunque los resultados pueden ser poco probables, esa posibilidad siempre existe.
Aunque claro, no caí en lo del valor ascii de la letra...

Un saludo!


12-Apr-2013 06:24
Jose Medrano

Hola, me quedo asi:


#include <stdio.h>

float raiz(float A, float B, float C,float *x1,float *x2)
{
	float Disc;
	Disc = (B*B) - (4*A*C);
	
	if(A==0)
	{
		printf("
Error!, esto es una ecuación de 1r. grado");

		return;
    }
	
	if(Disc>0)
	{
		*x1=(-B+sqrt(Disc))/(2*A);

		*x2=(-B-sqrt(Disc))/(2*A);

		printf("
Solucion x1= %.4f",*x1);

		printf("
Solucion x2= %.4f",*x2);
	}

	else if(Disc==0)
		 {	
			*x1=(-B)/(2*A);
			printf("
Solucion Doble= %.2f
",*x1);
		 }

	else 
		printf("ERROR !, raices imaginarias.
");

	
}

int main()
{
	float a,b,c;
	float x1, x2;
	printf("Introduce los coeficientes: ");
	scanf("%f%f%f",&a,&b,&c);
	raiz(a,b,c,&x1,&x2);
	system("pause");
	return 0;
}



PD: Mi duda es por que no anda si defino la funcion asi:

float raiz(float A, float B, float C)

float Disc;
       float *x1,*x2;

...etc


y luego en main llamo a raiz asi :

raiz(a,b,c)


Saludos !!


12-Apr-2013 08:47
Nacho Cabanes (+83)

La apariencia en general es buena.

Lo ideal es que si la función devuelve valores, no escriba nada en pantalla, porque se supone que los devuelve para que esos valores sean analizados desde "main".

Y en cuanto al motivo por el que no funciona... pues es porque para devolver varios valores usando parámetros por referencia... tienen que estar en la lista de parámetros. Todo lo que declares dentro de la función son variables locales, cuyo valor sólo existe dentro de la función y se pierde al salir.







(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)