Errore nel calcolo delle percentuali - 2
Moderatori: roby, Moderators
Riassumo la logica della funzione così è più facile isolare l'argomento di dibattito:
- parametri in ingresso sono un array dei valori e il totale rispetto al quale calcolare la percentuale.
- carico l'array temp2 con i "resti" necessari ad ogni valore per ottenere lo 0,01 in piu'
- contemporaneamente carico l'array temp3 con le stesse percentuali calcolate
- e calcolo la somma delle percentuali calcolate con due decimali.
- Verifico che tale somma non sia superiore a 100, se lo è apro un ciclo e decremento di 0,01 il temp3 corrispondente al temp2 più alto, quindi azzero questo temp2 in modo da escluderlo dai successivi decrementi (se i valori fossero tutti a zero la somma delle percentuali non potrebbe essere diversa da 100).
- per ovviare al problema della precisione eseguo un controllo testuale della somma delle percentuali (che a questo punto non può essere superiore a 100) e se è 100 la funzione termina ritornando l'array delle percentuali
- altrimenti controllo che la somma non sia inferiore a 100 e se lo è entro nel ciclo di incremento corrispondente concettualmente a quello di decremento.
- a questo punto la somma delle percentuali è sicuramente 100 quindi la funzione restituisce l'array delle percentuali.
Roberto
- parametri in ingresso sono un array dei valori e il totale rispetto al quale calcolare la percentuale.
- carico l'array temp2 con i "resti" necessari ad ogni valore per ottenere lo 0,01 in piu'
- contemporaneamente carico l'array temp3 con le stesse percentuali calcolate
- e calcolo la somma delle percentuali calcolate con due decimali.
- Verifico che tale somma non sia superiore a 100, se lo è apro un ciclo e decremento di 0,01 il temp3 corrispondente al temp2 più alto, quindi azzero questo temp2 in modo da escluderlo dai successivi decrementi (se i valori fossero tutti a zero la somma delle percentuali non potrebbe essere diversa da 100).
- per ovviare al problema della precisione eseguo un controllo testuale della somma delle percentuali (che a questo punto non può essere superiore a 100) e se è 100 la funzione termina ritornando l'array delle percentuali
- altrimenti controllo che la somma non sia inferiore a 100 e se lo è entro nel ciclo di incremento corrispondente concettualmente a quello di decremento.
- a questo punto la somma delle percentuali è sicuramente 100 quindi la funzione restituisce l'array delle percentuali.
Roberto
Quindi, ragionando in maniera opposta a come funziona il ciclo di decremento, quello di incremento dovrebbe aumentare di 0,01 il temp3 corrispondente al temp2 più basso, e poi viene messo a 1 quel temp2 in modo da escluderlo dai successivi incrementi.roby ha scritto: [...]
apro un ciclo e decremento di 0,01 il temp3 corrispondente al temp2 più alto, quindi azzero questo temp2 in modo da escluderlo dai successivi decrementi (se i valori fossero tutti a zero la somma delle percentuali non potrebbe essere diversa da 100).
[...]
- altrimenti controllo che la somma non sia inferiore a 100 e se lo è entro nel ciclo di incremento corrispondente concettualmente a quello di decremento.
[...]
Però ci possono essere casi in cui il temp2 più basso è uguale a zero, proprio perché per alcuni valori non ci sono stati arrotondamenti (magari perché il numero di voti/schede è uguale a zero, o - caso meno frequente - è un sottomultiplo del totale dei voti e pertanto la percentuale è già arrotondata alla seconda cifra decimale), e sarebbe giusto lasciare invariate queste percentuali, modificando solo quelle hanno effettivamente subito un arrotondamento.
La mia proposta consisteva nell'escludere, dal ciclo di incrementi, quei temp3 che non sono stati arrotondati, impostando a 1 il corrispondente temp2 - il tutto ancora prima che inizi il ciclo di incrementi vero e proprio.
Sto ragionando in maniera corretta?
Daniele
Si il ragionamento concettualmente è giusto, direi di inserire un controllo che consenta la chiamata alla funzione solo se almeno uno dei valori è maggiore di zero, per quanto riguarda il caso in cui il temp2 più basso è uguale a zero direi che la funzione risponde correttamente perché in questo caso i temp2 sono tutti uguali a zero (non potendo essere negativi) quindi non ci sono arrotondamenti da fare, la somma delle percentuali è già 100.00 e la funzione termina.
Roberto
Roberto
Mi spiego meglio riportandoti i dati del mio caso specifico.
Questi sono i valori su cui vengono calcolate le percentuali:
- Voti Validi: 17126
- Schede Nulle: 297
- Schede Bianche: 127
- Voti Contestati: 0
- Voti Nulli: 0
Questi sono i valori degli array temp3 e temp2 PRIMA del ciclo di incremento:
97.58 - 0.159544159544
1.69 - 0.0769230769231
0.72 - 0.763532763533
0.00 - 0
0.00 - 0
Questi sono i valori degli array temp3 e temp2 DOPO il ciclo di incremento:
97.58 - 0.159544159544
1.69 - 0.0769230769231
0.72 - 0.763532763533
0.01 - 1
0.00 - 0
Un eventuale controllo che consenta la chiamata alla funzione solo se almeno uno dei valori è maggiore di zero avrebbe - in questo caso - successo, e la funzione verrebbe eseguita.
Purtroppo però, tra questi valori, c'è anche qualche temp2 uguale a zero, ed è proprio uno di questi ad essere vittima dell'incremento di un punto percentuale!
Daniele
Questi sono i valori su cui vengono calcolate le percentuali:
- Voti Validi: 17126
- Schede Nulle: 297
- Schede Bianche: 127
- Voti Contestati: 0
- Voti Nulli: 0
Questi sono i valori degli array temp3 e temp2 PRIMA del ciclo di incremento:
97.58 - 0.159544159544
1.69 - 0.0769230769231
0.72 - 0.763532763533
0.00 - 0
0.00 - 0
Questi sono i valori degli array temp3 e temp2 DOPO il ciclo di incremento:
97.58 - 0.159544159544
1.69 - 0.0769230769231
0.72 - 0.763532763533
0.01 - 1
0.00 - 0
Un eventuale controllo che consenta la chiamata alla funzione solo se almeno uno dei valori è maggiore di zero avrebbe - in questo caso - successo, e la funzione verrebbe eseguita.
Purtroppo però, tra questi valori, c'è anche qualche temp2 uguale a zero, ed è proprio uno di questi ad essere vittima dell'incremento di un punto percentuale!
Daniele
Ho pensato che hai ragione tu e gli elementi che non devono avere incrementi o decrementi non vanno inseriti nell'array di controllo, così ho rivisto la funzione apportando anche una correzione (nella funzione ceil la moltiplicazione va fatta per 10000 e non per 1000).
Ho anche risistemato 02_risultati e 01_votanti per formattarne l'output grafico.
Il pacchetto con i tre file si scarica da qui:
Modifico il messaggio per ulteriori modifiche, scaricare e applicare in ordine:
http://trac.eleonline.it/eleonline/chan ... zip&new=73
http://trac.eleonline.it/eleonline/chan ... zip&new=74
http://trac.eleonline.it/eleonline/chan ... zip&new=75
http://trac.eleonline.it/eleonline/chan ... zip&new=76
Buona rientro a tutti.
Roberto
Ho anche risistemato 02_risultati e 01_votanti per formattarne l'output grafico.
Il pacchetto con i tre file si scarica da qui:
Modifico il messaggio per ulteriori modifiche, scaricare e applicare in ordine:
http://trac.eleonline.it/eleonline/chan ... zip&new=73
http://trac.eleonline.it/eleonline/chan ... zip&new=74
http://trac.eleonline.it/eleonline/chan ... zip&new=75
http://trac.eleonline.it/eleonline/chan ... zip&new=76
Buona rientro a tutti.
Roberto
E' anche possibile scaricare tutti i file modificati dalla versione 73 alla 76 in un unico pacchetto da questo indirizzo:
https://trac.eleonline.it/eleonline/cha ... d_path=%2F
Cartelle compresse di windows non riesce a gestire il pacchetto zip che viene prodotto, ma altri prodotti, ad esempio winrar, non hanno problemi.
Roberto
https://trac.eleonline.it/eleonline/cha ... d_path=%2F
Cartelle compresse di windows non riesce a gestire il pacchetto zip che viene prodotto, ma altri prodotti, ad esempio winrar, non hanno problemi.
Roberto
Ho caricato la versione aggiornata, ma continua a darmi il problema (vedi: http://elezioni.comune.lugo.ra.it/clien ... id_lista=0).
Ho visto che hai aggiunto, nell'IF, il controllo "or $temp2tot==0", ma non basta, perché nel mio caso $temp2tot vale 99.99, e pertanto il ciclo di incremento viene eseguito: questo comporta l'incremento di una percentuale che non aveva avuto alcun arrodontamento...
Bisognerebbe trovare il modo di escludere, all'interno del ciclo di incremento, la modifica di quei valori che non sono stati arrotondati.
Come primo tentativo avevo provato a modificare queste righe:
così:
ma lo script va in loop infinito, poiché min($temp2) vale ancora zero.
Bisogna modificare l'array $temp2, affinché il suo valore minimo rispecchi l'effettivo arrotondamento più basso, anziché il "non-arrotondamento".
La prima soluzione che avevi prospettato (cioè, inserire la linea "foreach ($temp2 as $key => $val) if($val==0) $temp2[$key]=1;" prima del secondo ciclo) è una strada percorribile: in questo modo si escludono i "non-arrotondamenti".
Daniele
Ho visto che hai aggiunto, nell'IF, il controllo "or $temp2tot==0", ma non basta, perché nel mio caso $temp2tot vale 99.99, e pertanto il ciclo di incremento viene eseguito: questo comporta l'incremento di una percentuale che non aveva avuto alcun arrodontamento...
Bisognerebbe trovare il modo di escludere, all'interno del ciclo di incremento, la modifica di quei valori che non sono stati arrotondati.
Come primo tentativo avevo provato a modificare queste righe:
Codice: Seleziona tutto
foreach ($temp2 as $key => $val) {
if ($val == min($temp2)) {$temp3[$key]+=0.01;$temp2tot+=0.01;$temp2[$key]=1;break;}
}
Codice: Seleziona tutto
foreach ($temp2 as $key => $val) {
if ($val!=0) {
if ($val == min($temp2)) {$temp3[$key]+=0.01;$temp2tot+=0.01;$temp2[$key]=1;break;}
}
}
Bisogna modificare l'array $temp2, affinché il suo valore minimo rispecchi l'effettivo arrotondamento più basso, anziché il "non-arrotondamento".
La prima soluzione che avevi prospettato (cioè, inserire la linea "foreach ($temp2 as $key => $val) if($val==0) $temp2[$key]=1;" prima del secondo ciclo) è una strada percorribile: in questo modo si escludono i "non-arrotondamenti".
Daniele
in effetti la funzione non mi convince ancora, ma tornerei ad una delle tue prime proposte: non inserire i valori "tondi" tra quelli da prendere in considerazione per gli incrementi o decrementi. Considerato che:
1) l'array temp2 viene utilizzato solo per fare il controllo e
2) se i valori sono tutti tondi non sono necessari ritocchi
credo che per risolvere si potrebbe (come dicevi tu) non valorizzare, per i valori tondi e cioé a zero, temp2 in questo modo:
in modo che temp3 sia comunque valorizzato e temp2 non lo sia.
Che ne pensi?
Roberto
1) l'array temp2 viene utilizzato solo per fare il controllo e
2) se i valori sono tutti tondi non sono necessari ritocchi
credo che per risolvere si potrebbe (come dicevi tu) non valorizzare, per i valori tondi e cioé a zero, temp2 in questo modo:
Codice: Seleziona tutto
$temp4=(ceil($voti*10000/$sevaltot)-($voti*10000/$sevaltot));
if ($temp4) $temp2[$key]=$temp4;
$valperc=number_format($voti*100/$sevaltot,2);
Che ne pensi?
Roberto
Inserita nel trunk. Nel frattempo avevo anche inviato la funzione per la cancellazione delle consultazioni che, visto che si parla di cancellazione definitiva dei dati, consiglio di provare solo dopo adeguato dump del DB. Si trova nel menu "Autorizza comuni", quindi "edit" sulla consultazione, spunta per abilitare la cancellazione, scelta della voce cancellazione nel combo dello stato e infine pulsante "Cancella consultazione". La cancellazione riguarda i dati del singolo comune mentre manca ancora la cancellazione totale della consultazione che penso di inserire nel menu "Consultazione" del superuser.
Valutazioni e consigli sono sempre graditi.
Roberto
Valutazioni e consigli sono sempre graditi.
Roberto