problema della funzione val()

salve ho notato che la funzione Val() restituisce un valore anomalo, e questo lo si pu notare direttamente nel debugger.
Facciamo l’ipotesi di avere
una stringa s=“2.34”
una variabile r double
se faccio
r=val(s) ottengo 2.33999999 invece di 2.34
questo lo si nota nel debugger , all’interno del quale si notano i valori assunti da s e da r …

Si, normale
io ho ovviato l’inconveniente utilizzando una variabile di tipo currency
2,34 diventerebbe 2,3400
almeno ti fermi al 4^ decimale
Per i database definiscili tranquillamente come double
ma li scrivi e li leggi come currency ad esempio :
row.currencycolumn(“prezzo”) = variabilecurrency
rs.field(“prezzo”).currencyvalue = variabilecurrency
variabilecurrency = rs.field(“prezzo”).currencyvalue

Poi adesso magari risponder Antonio con una soluzione pi efficace della mia…

scusa , ma non capisco perche " normale" …
nelle specifiche/esempio di uso della funzione val si legge questo

Examples

These examples use the Val function to return the numbers contained in a string.
Dim n As Double
n = Val(“12345”) //returns 12345
n = Val(“54.05car45”) //returns 54.05
n = Val(“123.45”) //returns 123.45
n = Val(“123 45”) //returns 123
n = Val(“123,456”) //returns 123
n = Val(“auto”) //returns 0
n = Val("&hFFF") //returns 4095
n = Val("&b1111") //returns 15

Dim s As String
s = “12345”
n = s.Val //returns 12345

non mi pare evidenziato l’atteggiamento che risulta dal debugger

http://documentation.xojo.com/index.php/Val

Yuri quella guerr li la ho affrontata gi dalla versione 2013…
io tra l’altro utilizzo cdbl invece di val,
la prima tiene conto delle impostazioni internazionali per la formattazione dei numeri+
la seconda no.

Poi per l’appunto. se cerchi qui nel forum c’ almeno un mio post dove lamento la stessa tua situazione.

annamoBBBene , proprioBBBEne ! tanto ne avesse poche di beghe xojo

Questa e’ una cosa molto comune con i numeri in virgola mobile e non dipende da Xojo…

questa e’ una conversione di un testo in un numero !
se ho una stringa che ha un valore finito e 2 decimali , se la converto in un numero, non posso ritrovarmi un numero con 10 decimali e valore diverso rispetto a quello in stringa… che c’entrano i numeri in virgola mobile !
poi,
perch in tal caso non lo segnalano come eccezione ??
negli esempi della funzione val , affermano il falso dicendo che si comporta come da loro esempio
n = Val(“123.45”) //returns 123.45

in realt restituisce 123.449999999999

Perche’ non tutti i numeri non interi sono rappresentabili esattamente in virgola mobile.

But it’s not precise: A floating point values primer

Esatto. Non esiste una rappresentazione di un numero come 123.45 nella struttura che viene utilizzata DA TUTTI in virgola mobile.

Se hai bisogno di una precisione definita, devi utilizzare una struttura “tipo” currency, ovvero un intero che in realt rappresenta i centesimi o la tua precisione.

Su macOS ad esempio oltre i vari tipi standard esiste NSDecimal. Ma qui andiamo sulle rappresentazioni “private” ovvero non cross platform.

Benvenuto nei problemi del calcolo numerico.

Il lato positivo, che se non hai bisogno di un precisione elevatissima, il numero sar (a parte casi particolari) sempre lo “stesso”.
Voglio dire, cerca di verificare se alla fine dei calcoli hai delle differenze, non fare l’ottimizzazione precoce (in questo caso la preoccupazione precoce)

scusate ma forse sono io che non ho sufficenti basi culturali per comprendere la cosa.

io parlo di un dato numerico ( e non un risultato tra divisioni o calcoli simili) che e’ rappresentato in una stringa
quindi, se ho una stringa che contiene un dato numerico finito , quindi con 2 decimali … tipo s=“123.45”
non potete dire che questa conversione implica una rappresentazione numerica che poi induce 10 decimali !!
cio val(“123.45”) non pu dar vita a un risultato pari a 123.449999999999
anche perche altrimenti, dovreste spiegare come mai negli esempi riportati sulla documentazione
pagina specifica : http://documentation.xojo.com/index.php/Val

viene riportato il seguente esempio
Dim n As Double
n = Val(“12345”) //returns 12345
n = Val(“54.05car45”) //returns 54.05
n = Val(“123.45”) //returns 123.45

vedete che scrivono n = Val(“123.45”) //returns 123.45 e non return 123.44999999999 !!!

della rappresentazione dei numeri con virgola mobile, detto fra di noi, se pago una licenza di un ide per sviluppo di applicativi che possano compiere calcoli in virgola mobile , NON ME NE DEVE FREGARE ASSOLUTAMENTE NIENTE !!!

ALTRIMENTI DEVO PRESUPPORRE CHE SE VADO A FARE UNA SOMMA ,EFFETTO CALCOLO DELL’AMMONTARE/CASTELLETTO DELL’IVA DI UNA FATTURA LUNGHISSIMA E CON TANTI ARTICOLI, IL RISULTATO FINALE SARA ASSOLUTAMENTE ED INEVITABILMENTE ERRATO, IN QUANTO CI SONO REALTA I CUI PREZZI UNITARI O DEFINIZIONE DELLA QUANTITA’, POSSONO AVERE ANCHE 4/5 DECIMALI !!

ps. Ho provato ad eseguire lo stesso codice nel vecchio ed antiquato visual basic 6.0 e questi problemi non esistono minimamente , antonio, mi dirai mica che vb6 usa altre rappresentazioni dati in virgola mobile !

Non un problema di Xojo, un problema di rappresentazione binaria dei dati. In memoria, nel processore hai solo bit non hai numeri.
se chiedi un double, vuol dire che hai un numero in virgola mobile.
Come spiegato nell’articolo linkato prima da Maurizio, i numeri vengono memorizzati come potenze di 2.

Ma non che lo scrivere in potenza di 10, di solito fai sulla carta, risolva il problema: quanto fa 1/3?
Per quanto vuoi essere preciso ad un certo punto approssimi e tagli il resto.
Come vedi non un problema nuovo il problema del valore simbolico di un numero e della sua rappresentazione.
Per quanto puoi prendere grande la rappresentazione ci saranno sempre numeri che non potrai rappresentare correttamente: la rappresentazione finita, per cui ci saranno due numeri tra cui non ci sono numeri, mentre tra i reali tra due numeri qualsiasi ci sono infiniti numeri.

Detto questo il tuo problema solo un problema di contenere l’approssimazione all’interno di un range accettabile.
In contabilit semplice, ovvero al massimo in centesimi, usi il currency o interi che rappresentano i centesimi e non il valore monetario unitario. Qui hai una rappresentazione esatta perch l’approssimazione l’hai spostata alla definizione dell’insieme monetario: tra due centesimi contigui non ci sono altri valori.

Tornando al tuo esempio in vb6, questo rappresenta il numero con il numero di decimali minimi, non che il numero realmente quello. Anzi, quel tipo di conversione induce errori: 123.44999999999 una parte in realt continua
Prova a fare:
dim a as double=123.45
dim b as double=a/3
dim c as double=b*3
dim d as double=c-a

Vedrai che l’approssimazione indotta di una parte su 100 mila miliardi su un numero di grandezza 2 (ordine delle centinaia)
pi o meno come se stessi conteggiando i km di una autovettura e di preoccupi della differenza di Angstrom.

Lo standard IEEE questo. Prova con javascript, Xcode o quello che vuoi.

Ripeto non un problema che riscontri in Xojo.
Ottimizzando una procedura MatLab mi sono trovato a dover fronteggiare errori di approssimazione. Per poi riscontrare che era corretto il calcolo di Xojo e quello di MatLab, nella configurazione che mi avevano consegnato, in pratica approssimava a valori pi bassi.

Per concludere: c’ un motivo per cui i test di convergenza richiedono che il delta di chiusura (indifferenza del risultato) sia al di sotto di un valore e non esattamente 0.

puoi scrivere quanto vuoi ma il test l’ho fatto in vb6 e il problema in questo ambiente non esiste .
poi, l’uso del currency non risolve , in quanto e’ la funzione di conversione da stringa a numero che ha il problema in se

POI,

PERCHE XOJO NON MODIFICA L’ESEMPIO CHE PROPONE NELL’USO DELLA FUNZIONEN VAL() ???
potrebbero aggiornare la documentazione dicendo che la funzione val() NON FARA LA CONNVERSIONE PER COME LA ESPONGONO NELLA DOCUMENTAZIONE !

RIPETO CHE NELLA DOCUMENTAZIONE SCRIVONO :
(estratto documentazione xojo)
Dim n As Double
n = Val(“123.45”) //returns 123.45 <<--------- E QUESTO E’ FALSO ! perche torna 123.449999999 !!!

poi ,puoi parlarmi anche di filosofia !!
vb6 questo errore non lo fa e dubito che lo facciano altri compilatori (come invece tu affermi)
di fatto, non puoi sempre usare un dato di tipo currency, perche esistono casi in cui il riferimento o l’unita di misura e’ il grammo o l’unit (tipo una vite e il prezzo e’ al kg) o e tu vendi materiale che pesa un millesimo di grammo o costa 0,00023 euro al pezzo.
a quel punto introduci un errore grave sia nel calcoro dell’importo riga , sia un errore nel calcolo dell’iva , sia un errore nel calcolo dei totali finali.
e per alcuni di questi calcoli l’arrotondamento non e’ quello matematico (troppo facile) ma quello fiscale, il che complica ancora pi la vita !

QUESTO E’ UN PROBLEMA CHE DEVONO RISOLVERE … ALTRO CHE DISCUSSIONI INUTILI SULLA FILOSOFIA DELLA RAPPRENTAZIONE DEI NUMERI , UNA STRINGA =“123.45” DEVE DARE COME RISULTATO 123.45 QUALSIASI SIA IL TIPO DI NUMERO IN CUI LA CONVERTA (SEMPRE CHE TALE NUMERO LA POSSA CONTEMPLARE ).
DOPO CREO UN CASO , PERCHE’ TRA L’ALTRO SUL MANUALE SCRIVONO PURE IL FALSO.

Filosofia?

Scrivi alla IEEE e di modificare le cose. Gli standard sono questi.
Valuta gli ordini di grandezza prima che tu possa riscontrare un errore.

Vuoi vedere 123.45? usa msgbox(str(123.45,"##0.0000000")

Se poi riesci a rappresentare infiniti numeri in uno spazio finito… dimmi come fai

Dir di modificare l’esempio con n=Val(“123.25”) cos hai 123.25 e sei soddisfatto

senti a me pare una cosa da idioti
io mica chiedo che si rappresentino dei numeri infiniti in uno spazio finito !!
chiedo che se ho una stringa rappresentabile in una forma double, il risultato di questa non sia diverso dal valore
della stringa
mi vuoi dire che un valore stringa “2.34” non e’ convertibile in un double =2.34 ???
ma mi pigli in giro ???

poi, se ci sono dei limiti di rappresentabilit saranno agli estremi alti e bassi di questa , potrai indicare nella funzione il numero massimo di cifre decimali combinate con un numero massimo di cifre della parte intera …
ma non che un numero stringa rappresentabilissmo (2.34), sia convertito in una cosa inesistente 2.339999999999 , questa si chiama presa per il…

poi , perche VB6 di un milione di anni fa, NON HA QUESTO PROBLEMA ???

Perch vb ti fa vedere il numero approssimato che nel caso specifico quello che ti aspetti, mentre Xojo, pi onestamente ti fa vedere il vero valore che in realt utilizzato.
Questo ti permette nel famoso caso di approssimazioni successive (ma ripeto ce ne vogliono tantissime) di capirne la fonte e nel caso sai dove e come intervenire.
vb mente.
Ti fa vedere un valore che poi non utilizza
Questo, sempre nel caso delle approssimazioni successive, non ti dar nessun indizio di dove i valori sono errati.

Hai la stessa cosa in excel, in calcoli con molti decimali alla fine potresti avere dati che sembrano errati perch vedi numeri con 2 decimali (basta una semplice fattura, ci sono casi di numeri in cui se fai le singole approssimazioni, ovvero tieni per vero il valore mostrato, non ottieni lo stesso valore calcolato: LEGALMENTE ha valore il valore calcolato non quello rappresentato.)

Il numero che Xojo ti fa vedere quello “reale” che tratta. Puoi sempre, ripeto, utilizzare str con il formato per decidere quanti decimali ti servono. Ma la realt non cambia: ogni bit nel numero rappresenta una divisione per due del valore precedente (cos come quelli prima della virgola rappresentano una moltiplicazione per 2) per cui avrai rappresentazioni “precise” di .5, .25, .125 cos via. Lo fanno tutti. Chi non lo fa, semplicemente non te lo fa vedere.