CInt() c'è un bug o sono diventato scemo!?!?!?

mercoledì 24 dicembre 2008 - 12.56

Lanello Profilo | Senior Member

ciao,

spero con questo titolo di attirare l'attenzione di molta gente, per farvi partecipi del problema in cui mi sono imbatutto.

vi spiego il problema che dovevo risolvere:

ho realizzato un'applicativo per una catena di negozi, a poco tempo fa con il titolare dell'azienda stavamo progettando gli algoritmi di calcolo per la sua prossima "fidelity card"... e fin qui tutto bene, mettiamo tutto su carta, programmiamo il da farsi, dopodichè mi metto al pc.

prima regola di questa fidelity, il cliente ha diritto a guadagnare X punti ogni 10,00 € di spesa.

esempio:

100 € = (10 * X) pti
105 € = (10 * X) pti
109 € = (10 * X) pti

la necessità quindi è quella di dividere il totale dello scontrino per 10, togliere i decimali senza però effettuare arrotondamenti per eccesso e moltiplicare per X per calcolare il giusto numero di punti da attibuire.

una cosa elementare penso io....

faccio subito una funzione che è la seguente:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

in questo caso il nostro X è 3 tanto per fare una prova...

qual'è stato il mio ragionamento...

divido il totale dello scontrino per 10, sottraggo 0.5 e trasformo in integer con la cara vecchia funzione cInt()

per quelli a cui non è chiaro, spiego perchè sottraggo 0.5 dal risultato della divisione...

totale scontrino | ris. divisione | arr. normale | -0.5 arrotondato |
100,00 € | 10,00 | 10 | 9.5 -> 10 |
199,99 € | 19,99 | 20 | 19.49 -> 19 |
213,00 € | 21,30 | 21 | 20.80 -> 20 |

quindi sottrarre 0,5 al risultato della divisione mi permette in ogni caso di eliminare l'arrotondamento per eccesso.

dov'è il problema?!?!!?

ecco un po di esempi:

499:10=49,9
tolgo 0.5 per arrotondare sempre per difetto = 49,4
arrotondo a numero intero = 49
moltiplico x 3 e trovo il punteggio = 147

199:10=19,9
tolgo 0.5 per arrotondare sempre per difetto = 19,4
arrotondo a numero intero = 19
moltiplico x 3 e trovo il punteggio = 57

110:10=11
tolgo 0.5 per arrotondare sempre per difetto = 10,5
arrotondo a numero intero = 10 <------ ERRORE
moltiplico x 3 e trovo il punteggio = 30

la funzione cInt() in barba alle leggi matematiche, arrotonda il X,5 per difetto invece che per eccesso!!!!!

http://it.wikipedia.org/wiki/Arrotondamento

per ora ho risolto sottraendo 0,49999999999 anzichè 0,5 ma non mi pare la soluzione più elegante del pianeta, se avete delle idee... grazie e Buon Natale a tutti/e
----------------------------------------------------------------------
http://www.flashinlabs.biz o .com o .net o .it fate voi :P

Anonimo Profilo | Senior Member

La mia non è proprio un'idea ma è piuttosto un'osservazione.
Come giustamente detto anche dal link che hai postato, l'arrotondamento se la cifra decimale è uguale a 5 e seguita da 0 non viene fatto nessun arrotondamento, semplicemente viene scartata, ti cito dove viene detto:

"Lasciare inalterata la cifra che precede quella da scartare, se la cifra da scartare è uguale a 5 ed è seguita da zeri o da nessuna altra cifra. Così V = 15.125 diventerà V = 15.12"

Dai un occhio a quanto detto qui:
http://www.roma1.infn.it/~dagos/BMS/node36.html


Riccardo

alx_81 Profilo | Guru

>ciao,
Ciao!

>dov'è il problema?!?!!?
>ecco un po di esempi:
>
>499:10=49,9
>tolgo 0.5 per arrotondare sempre per difetto = 49,4
>arrotondo a numero intero = 49
>moltiplico x 3 e trovo il punteggio = 147
>
>199:10=19,9
>tolgo 0.5 per arrotondare sempre per difetto = 19,4
>arrotondo a numero intero = 19
>moltiplico x 3 e trovo il punteggio = 57
>
>110:10=11
>tolgo 0.5 per arrotondare sempre per difetto = 10,5
>arrotondo a numero intero = 10 <------ ERRORE
>moltiplico x 3 e trovo il punteggio = 30

>la funzione cInt() in barba alle leggi matematiche, arrotonda
>il X,5 per difetto invece che per eccesso!!!!!
>http://it.wikipedia.org/wiki/Arrotondamento
Sì, ok queste sono le specifiche di arrotondamento. Ma la CInt è una funzione (che dovresti smettere di usare cercando di utilizzare piusttosto una CType o una Integer.Parse) che non è fatta per arrotondare, ma per castare un tipo diverso da int in int.
Nella guida sulla CInt è scritto

"When the fractional part is exactly 0.5, the CInt function always rounds it to the nearest even number. For example, 0.5 rounds to 0, and 1.5 rounds to 2. "
Noterai che il comportamento è quello che la documentazione evidenzia.

Utilizza la funzione Floor e prova a vedere se fa al caso tuo:
http://msdn.microsoft.com/it-it/library/e0b5f0xb(VS.80).aspx

>idee... grazie e Buon Natale a tutti/e
di nulla! Auguri anche a te!
--

Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

Lanello Profilo | Senior Member


>"When the fractional part is exactly 0.5, the CInt function always
>rounds it to the nearest even number. For example, 0.5 rounds
>to 0, and 1.5 rounds to 2. "
>Noterai che il comportamento è quello che la documentazione evidenzia.

e dal titolo del post, quindi, si evince che sono io che sono diventato scemo, in quanto non ho controllato la documentazione della funzione prima di postare e fare questa figuraccia

>Utilizza la funzione Floor e prova a vedere se fa al caso tuo:

di questa magnifica funzione non conoscevo ancora l'esistenza! è quello di cui ho bisogno, ho già sostituito infatti il contenuto della mia funzione nell'applicativo.

ri-grazie e Buon Natale a tutti/e


----------------------------------------------------------------------
http://www.flashinlabs.biz o .com o .net o .it fate voi :P
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5