Oppure

Loading
04/02/10 8:23
MagoAntò
Ciao a tutti!

Sono alle prese con un esercizio (anzi, una serie di esercizi) che mi richiedono, tra le altre cose, il calcolo dell'errore di round off. L'esercizio mi chiede di utilizzare una variabile double (nello specifico, double x)come risultato esatto e una variabile float (nello specifico, flx = (float)x) come sua approssimazione. Il calcolo dell'errore di round off viene, infine, eseguito calcolando l'errore relativo secondo questa formula: |x-flx|/|x|.

Vi riporto la traccia dell'esercizio:
Visualizzare l’errore di roundoff nei seguenti algoritmi. Scrivere una function C per calcolare una somma di molti addendi mediante l’algoritmo del raddoppiamento ricorsivo (batch adding - versione iterativa).

Diciamo che già la frase "raddoppiamento ricorsivo (versione iterativa)" già mi lascia un po' perplesso. Per raddoppiamento ricorsivo si intende una situazione del genere: abbiamo questi elementi

0 2 6 3 4 2

la somma totale, ovviamente, è 17 e la si deve ottenere con una funzione che somma prima 0+2 poi 6+3 poi 4+2, dopodichè somma i rispettivi risultati (2, 9, 6) facendo 2+9, il risultato +6 cioè 11+6 = 17

Ho deciso di implementare l'algoritmo ricorsivamente, in ogni caso. Questo è il codice:
#include <stdio.h>
#include <math.h>
#include <float.h>

float somma_radd_ric (float a [], float primo, float ultimo);

void main ()
{

	float a [50];
	float errore_roundoff, primo, ultimo, risultato;
	double risultato_esatto;
	int i, size;
	primo = 0;
	risultato_esatto = 0;
	printf ("Digita il numero degli addendi (max. 50): ");
	scanf ("%d", &size);
	ultimo = size-1;
	for (i=0; i<size; i++)
	{
		printf ("Inserisci il %d addendo: ", i+1);
		scanf ("%f", &a[i]);
		risultato_esatto = risultato_esatto + (double)a[i];
	}
	risultato = somma_radd_ric (a, primo, ultimo);
	printf ("Il risultato e' = %f\n", risultato);
	errore_roundoff = fabs ((risultato_esatto-risultato)/risultato_esatto);
	printf ("L'errore di roundoff e' = %e\n", errore_roundoff);
}

float somma_radd_ric (float a [], float primo, float ultimo)
{
	float mediano;
	if (ultimo - primo == 1)
		return (a[primo] + a[ultimo]);
	if (ultimo==primo)
		return (a[primo]);
	else
	{
		mediano = (primo+ultimo)/2;
		return (somma_radd_ric (a,primo,mediano) + somma_radd_ric (a,mediano+1,ultimo));
	}
}

Il codice mi da questi errori:

* warning C4244: '=' : conversion from 'int ' to 'float ', possible loss of data,
relativo alla riga "ultimo = size-1;"

* warning C4244: '=' : conversion from 'double ' to 'float ', possible loss of data,
relativo alla riga "errore_roundoff = fabs ((risultato_esatto-risultato)/risultato_esatto);"

* error C2108: subscript is not of integral type,
relativo alla riga "return (a[primo] + a[ultimo])";

* error C2108: subscript is not of integral type,
relativo alla riga "return (a[primo] + a[ultimo])";

* error C2110: cannot add two pointers,
relativo alla riga "return (a[primo] + a[ultimo])";

* warning C4033: 'somma_radd_ric' must return a value,
relativo alla riga "return (a[primo] + a[ultimo])";

* error C2108: subscript is not of integral type,
relativo alla riga "return (a[primo])";

* error C2115: 'return' : incompatible types,
relativo alla riga "return (a[primo])";

Il problema è il seguente: la function sembra funzionare solo nel caso in cui i parametri di input e di output vengano dichiarati come int. Nel momento in cui cambio i tipi di dato, succede quello che ho elencato sopra. Avevo pensato di dichiarare l'array e il risultato esatto come campi di una union, in modo da condividere la stessa area di memoria. Qualche aiuto? E' molto importante! Grazie in anticipo a tutti :)
Ultima modifica effettuata da MagoAntò 04/02/10 10:08
aaa
04/02/10 18:25
Poggi Marco
Ciao!

Ho letto il tuo programma, e ho trovato che tu usi dati float come indice della matrice.

Non ho ben capito come vorresti costruire l' union.
Ultima modifica effettuata da Poggi Marco 04/02/10 18:27
aaa
04/02/10 21:10
MagoAntò
Postato originariamente da Poggi Marco:

Ciao!

Ho letto il tuo programma, e ho trovato che tu usi dati float come indice della matrice.

Non ho ben capito come vorresti costruire l' union.

Ciao e grazie per la risposta.

Beh, prima ancora di creare l'union, vorrei capire perchè il programma, impostato così, mi da quegli errori.
Per quanto riguarda la union, avevo pensato ad una cosa del genere:
union bit_64bit
{
double dx;
_int64 y;
}a;

...visto che il mio codice sembra dare problemi nel momento in cui uso variabili float al posto delle int. Qualche altra idea?
aaa
05/02/10 7:27
nessuno
Gli indici di un vettore *devono* essere interi, non double o float ...

In particolare, devono essere intere le variabili primo, ultimo e mediano ...
Ultima modifica effettuata da nessuno 05/02/10 7:29
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
05/02/10 10:59
MagoAntò
Postato originariamente da nessuno:

Gli indici di un vettore *devono* essere interi, non double o float ...

In particolare, devono essere intere le variabili primo, ultimo e mediano ...


Dico una sciocchezza: dichiarandoli come interi, non riduco la precisione dei risultati? Dovrei calcolarli sia come float che come double, per questo dicevo... :-|
aaa
05/02/10 11:14
nessuno
Postato originariamente da MagoAntò:

Postato originariamente da nessuno:

Gli indici di un vettore *devono* essere interi, non double o float ...

In particolare, devono essere intere le variabili primo, ultimo e mediano ...


Dico una sciocchezza: dichiarandoli come interi, non riduco la precisione dei risultati? Dovrei calcolarli sia come float che come double, per questo dicevo... :-|


Cosa c'entra la precisione del calcolo con gli indici di un array? Stai facendo confusione tra gli elementi di un array e i suoi indici ...
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
05/02/10 12:26
MagoAntò
Postato originariamente da nessuno:

Postato originariamente da MagoAntò:

Postato originariamente da nessuno:

Gli indici di un vettore *devono* essere interi, non double o float ...

In particolare, devono essere intere le variabili primo, ultimo e mediano ...


Dico una sciocchezza: dichiarandoli come interi, non riduco la precisione dei risultati? Dovrei calcolarli sia come float che come double, per questo dicevo... :-|


Cosa c'entra la precisione del calcolo con gli indici di un array? Stai facendo confusione tra gli elementi di un array e i suoi indici ...


Hai ragione, scusami. ;)

Ho modificato il codice dichiarando primo, ultimo e mediano come interi, adesso il programma funziona. Inoltre, ho dichiarato l'array a come double in modo da poter calcolare meglio il risultato "esatto". La function somma_radd_ric, poi, provvederà a restituirmi il risultato come un float. Ho ragionato bene? Ecco il codice modificato:
#include  <stdio.h>
#include <math.h>
#include <float.h>

float somma_radd_ric (double a [], int primo, int ultimo);

void main ()
{

    double a [50];
    float risultato;
    double risultato_esatto, errore_roundoff;
    int i, size, primo, ultimo;
    primo = 0;
    risultato_esatto = 0;
    printf ("Digita il numero degli addendi (max. 50): ");
    scanf ("%d", &size);
    ultimo = size-1;
    for (i=0; i<size; i++)
    {
        printf ("Inserisci il %d addendo: ", i+1);
        scanf ("%lf", &a[i]);
        risultato_esatto = risultato_esatto + a[i];
    }
    printf ("Il risultato calcolato come double e': %lf\n", risultato_esatto);
    risultato = somma_radd_ric (a, primo, ultimo);
    printf ("Il risultato e' = %f\n", risultato);
    errore_roundoff = fabs ((risultato_esatto-risultato)/risultato_esatto);
    printf ("L'errore di roundoff e' = %e\n", errore_roundoff);
}

float somma_radd_ric (double a [], int primo, int ultimo)
{
    int mediano;
    if (ultimo - primo == 1)
        return (a[primo] + a[ultimo]);
    if (ultimo==primo)
        return (a[primo]);
    else
    {
        mediano = (primo+ultimo)/2;
        return (somma_radd_ric (a,primo,mediano) + somma_radd_ric (a,mediano+1,ultimo));
    }
}

Come test, ho provato ad inserire 50 componenti nell'array tutte uguali a 999999999999999 e, come output, il programma mi da:

Il risultato calcolato come double e': 49999999999999984.000000
Il risultato e' = 49999999161237504.000000
L'errore di roundoff e' = 1.569325e-008

L'errore di roundoff è "abbastanza piccolo" da poter essere accettato. Infine, il programma mi segnala solo due warning:

* warning C4244: 'return' : conversion from 'double ' to 'float ', possible loss of data,
relativo alla riga della function "return (a[primo] + a[ultimo])";

* warning C4244: 'return' : conversion from 'double ' to 'float ', possible loss of data,
relativo alla riga della function "return (a[primo])";


Ho sbagliato qualcosa? Grazie mille per l'aiuto! :k:
Ultima modifica effettuata da MagoAntò 05/02/10 12:45
aaa
05/02/10 18:06
Poggi Marco
Ciao!

Finalmente hai terminato il programma!

Per quanto riguarda i warning, non preoccuparti più di tanto.
Il compilatore si aspetta un dato float a destra di return, mentre tu gli inserisci un double. Per risolvere il problema, basta fare un cast ( return (float) (a[primo])"; ).
Ultima modifica effettuata da Poggi Marco 05/02/10 18:08
aaa