Incredibile errore nell' istruzione if

di il
5 risposte

Incredibile errore nell' istruzione if

Salve a tutti ragazzi sono nuovo del forum, e dovrei risolvere un errore di esecuzione che ha dell'incredibile magari qualcuno ne sa di più...
In pratica volevo implementare l'algoritmo di gauss in c, dopo averlo finito e provato con alcuni tipi di sistemi mi è sorto questo errore algoritmico con un particolare tipo di sistema.
Come saprete il primo passo è quello di trovare il pivot della riga lungo la colonna nella matrice e l'ho fatto usando un ciclo while, accolo qui sotto (solo questo pezzo):
printf("\n i=%d j=%d stop=%d", i,j,stop);
		while(stop==0){
			printf("%f",sis[i][j]);
			if(sis[i][j]==0){
				printf("chekpoint");
				if(i<r-1){
					i++;
				}else{
					if(j<c-1){
						j++;
						i=d;
					}else{
						stop=1; //(i==r-1&&j==c-1)
					}
				}
			}else{
				stop=1;
			}
		}
		printf("\n\n i=%d j=%d", i,j);
l'errore è questo: l'istruzione "if(sis[j]==0)" non viene eseguita correttamete la printf sopra mi dice che l'elemento che viene controllato vale -0.00000 ma il programma passa al caso "else" comunque!!! perchè??

la matrice del sistema è la seguente:
1 2 3 4 5
5 4 3 2 1
6 7 8 9 0
2 3 4 5 6

Ad esempio questo non succede se immetto il sistema:
0 1 2
1 2 3
oppure
-0 1 2
1 2 3

Per chi è curioso di vedere quale sia l'errore con i suoi occhi questo è il programma completo:
#include<stdio.h>
#include<stdlib.h>

void errdt(int);
int rsis(float**, int, int, float*);

int main(){
	
	int r, c,i,j,e;
	float **sisM, *sol; //sisM è la matrice completa
	
	printf("\ninserisci numero righe e colonne\n");
	scanf("%d %d", &r,&c);
	if((sisM = (float**) malloc(r*sizeof(float*)))==NULL){
		printf("errore di allocazione");
		return(-1);
	}
	for(j=0;j<r;j++){
		if((sisM[j] = (float*) malloc(c*sizeof(float)))==NULL){
			printf("errore di allocazione");
			return(-1);
		}
	}//matrice dinamica allocata
	printf("\nhai inserito: %d righe e %d colonne", r,c);
	
	printf("\ninserisci i numeri e premi invio (matrice completa del sistema):\n");
	for(i=0;i<r;i++){
		for(j=0;j<c;j++)
			scanf("%f", &sisM[i][j]);
		
	}
	
	if((sol = (float*) malloc((c-1)*sizeof(float)))==NULL){
		printf("errore di allocazione");
		return(-2);
	}
	
	//stampa
	printf("\nmatrice inserita:");
	for(i=0;i<r;i++){
		printf("\n");
		for(j=0;j<c;j++)
			printf("%.2f ", sisM[i][j]);
	}
	
	e=rsis(sisM,r,c,sol);
	if(e!=0){
		errdt(e);
		for(i=0;i<r;i++)
			free(sisM[i]);
		free(sisM);
		free(sol);
		return(-3);
	}
	
	//stampa risultato
	printf("\n\nrisultato del sistema:\n");
	for(i=0;i<c-1;i++){
		printf("variabile %d: %.2f ", i+1, sol[i]);
	}
	
	for(i=0;i<r;i++)
		free(sisM[i]);
	free(sisM);
	free(sol);
	
}


int rsis(float** sis, int r,int c, float* sol){
	
	int i,j,a,b,d,rango=0;
	float temp;
	char stop;
	d=0;

	while(r-d>1){//se la matrice "schermata" ha più di una riga continua
		i=d;
		j=d;
		stop=0;
		printf("\n i=%d j=%d stop=%d", i,j,stop);
		while(stop==0){
			printf("%f",sis[i][j]);
			if(sis[i][j]==0){
				printf("chekpoint");
				if(i<r-1){
					i++;
				}else{
					if(j<c-1){
						j++;
						i=d;
					}else{
						stop=1; //(i==r-1&&j==c-1)
					}
				}
			}else{
				stop=1;
			}
		}
		printf("\n\n i=%d j=%d", i,j);
		if(sis[i][j]==0){//matrice "schermata" nulla (i==r-1&&j==c-1)
			if(d==0){
				return(1);//mat nulla
			}
		}else{
			if(i!=d){//scambio riga se non è pivot
				for(a=j;a<c;a++){
					temp=sis[d][a];
					sis[d][a]=sis[i][a];
					sis[i][a]=temp;
				}
			}
			
			for(a=i+1;a<r;a++){//annullo sotto il pivot
				temp=sis[a][j]/sis[i][j];
				for(b=j;b<c;b++)
					sis[a][b]=sis[a][b]-sis[i][b]*temp;//moltiplica per scalare la riga soprastante e la sottrae
			}
		}
		d++;
		printf("\nmatrice in scalo:");
		for(i=0;i<r;i++){
			printf("\n");
			for(j=0;j<c;j++)
				printf("%.2f ", sis[i][j]);
		}
	}//matrice ridotta a scala
	
	
	//rango
	i=r-1;j=0;
	while(rango==0){
		if(sis[i][j]!=0){
			rango=i+1;
		}else{
			if(j<c-1){
				j++;
			}else{
				if(i>0){
					i--;
					j=0;
				}else{
					return(1); //matrice nulla
				}
			}
		}
	}
	printf("\nrango della matrice completa: %d", rango);

	//risolvibilità sistema
	if(rango<c-1){//rango non massimo
		return(2);//sistema dipendente da parametri o impossibile
	}else{//rango>=c-1 ----> rango=c-1 (altro caso impossibile)	
		
		if(sis[rango-1][c-2]==0){
			return(3); //sistema impossibile (rango matrice incompleta diverso)
		}else{ //altrimenti sistema risolvibile univocamente
	
			i=rango-1;
			temp=0;
			
			sol[i]=sis[i][c-1]/sis[i][i];
			for(a=i-1;a>=0;a--){
				for(b=a+1;b<r;b++)
					temp=temp+sol[b]*sis[a][b];
				
				sol[a]=(sis[a][c-1]-temp)/sis[a][a];
			}
		}
	}
	//sistema risolto
	
	return(0);
}

void errdt(int e){
	
	switch(e){
	case 1:
		printf("\nmatrice nulla");
		break;
	case 2:
		printf("\nsistema dipendente da parametri o impossibile");
		break;
	case 3:
		printf("\nsistema impossibile");
		break;
	default:
		printf("\nerrore sconosciuto");
		break;
	}
	return;
}
Grazie mille per l'attenzione!!!

5 Risposte

  • Re: Incredibile errore nell' istruzione if

    Intanto la if non è una funzione ma un'istruzione ... poi l'errore non è incredibile dato che gli errori legati alla rappresentazione in virgola mobile sono noti.

    Ti consiglio di riprovare sostituendo tutti i float con dei double e vedere se il problema si ripresenta.
  • Re: Incredibile errore nell' istruzione if

    Scusate per lo "strafalcione"...
    comunque ho provato e il problema rimane!
  • Re: Incredibile errore nell' istruzione if

    Strano ... ho provato e la if viene eseguita. Quale compilatore usi?
  • Re: Incredibile errore nell' istruzione if

    Ok risolto!!! ho usato un long double... (anche se mi scoccia un po' utilizzare una variabile così grande)
    Il compilatore che uso è gcc.

    l'errore quindi è dovuto a un fatto di approssimazione?
  • Re: Incredibile errore nell' istruzione if

    Non è "grande" ma solo più "precisa".

    Sì è un errore di approssimazione dovuto ai "noti" problemi di rappresentazione dei valori decimali in binario.
Devi accedere o registrarti per scrivere nel forum
5 risposte