Newsgroup: it.comp.lang.visual-basic
Titolo: Estrarre la parte decimale di un numero

 Ho una variabile double 'Valore' che contiene 1278,87 qualcuno sa perchè
l'istruzione
decimale=VALORE - Int(VALORE)
restituisce la variabile 'decimale' con 0.869999999999891 invece di 0.87
come mi aspettavo ?
Come posso ottenere il valore corretto ?
 Ps.  non conosco a priori il numero di decimali che conterrà la variabile
'valore'

> scoglio:

Fatti quattro risate con questo approccio *scientifico*
tipicamente "BASIC".
Dim valore   As Double
Dim decimale As Double
valore = 1278.87
Debug.Print valore
decimale = valore - Int(valore)
Debug.Print decimale
decimale _
  = "0," _
  & Mid$(Format$(valore) _
  , InStr(Format$(valore) & ",", ",") + 1)
Debug.Print decimale
--
Ciao.
Maurizio
--------
?SPQR(C)
 X

 Come posso ottenere il valore corretto ?
prova a dare un occhiata alle funzioni Round(), Fix(), Int(), Format()
ciao

 come mi aspettavo ?
Perché è una variabile Double. Vedi la guida per una
descrizione del tipo.
Priva a dichiarare la variabile decimale come Single o
Variant, quindi
Dim VALORE As Double
Dim decimale As Variant
   VALORE = 1278.87
   decimale = CSng(VALORE - Int(VALORE))
    decimale sarà uguale a 0,87

  Ps.  non conosco a priori il numero di decimali che
conterrà la variabile 'valore'
per cui se, putacaso, volesse la parte decimale di:
    1278.987654321
si ritroverebbe con
    0,9876543
e non so se gli starebbe bene...
Credo che la strada migliore sia (solo VB6?):
    Dim Valore   As Double
    Dim Decimale As Double
    Valore = 1278.87
    Decimale = CDec(Valore) - Int(Valore)


 conterrà la variabile 'valore'
Non mi sono dimenticato.
Non l'ho visto e l'ho tagliato.
Quindi quello che scrivo in effetti è sbagliato.
Fa conto che io per estrarre la mantissa con VB converto in stringa.
Verrebbe più o meno così:
Dim VALORE As Double
Dim Mantissa As Double
Dim strBuff As String
   VALORE = 1278.8756578
   strBuff = CStr(VALORE)
   strBuff = "0" & Mid$(strBuff, InStr(strBuff, ","), 100)
   Mantissa = CDbl(strBuff)
Così almeno gli resta la mantissa come nel valore originale.
Anche con il metodo che suggerisci tu si becca l'arrotondamento.


Il perchè posso spiegartelo allegandoti la risposta che ho dato tempo fa sul
newsgroup ad una
mail molto simile che allego di sotto se non è abbastanza chiaro scrivi pure
al mio indirizzo privato
mine...@libero.it
 o posta sul news ancora
La domanda era del tipo perchè Access restituiva il seguente risultato
"sbagliato" all'operazione 4,56*4000,25=18251,140625 c'era anche uno che
aveva risposto dicendo
che Access restituiva più cifre di quelle richieste in realtà era
proprio un errore errore che è però noto e calcolato nella teoria
del calcono numerico al calcolatore:
Inizio allegato:
Innanzitutto non diciamo cazzate riguardo al fatto che access restituisce
più cifre del dovuto.
Vediamo se riesco ad essere chiaro.
Supponiamo di avere come è un numero di bit a disposizione limitato per
scrivere
un numero in binario in fpu (singola precisione)
il numero 4000,25 può essere facilmente scritto in binario com
111110100000,01
Se non capisci cerco di spiegarti a sinistra della virgola abbiamo le
potenze positive del due partendo da zero quindi da destra verso
sinistra avremo  (indicando con ^ l'elevamento a potenza)
0 * 2^0    = 0
0 * 2^1    = 0
0 * 2^2    = 0
0 * 2^3    = 0
0 * 2^4    = 0
1 * 2^5    = 32
0 * 2^6    = 0
1 * 2^7    = 128
1 * 2^8    = 256
1 * 2^9    = 512
1 * 2^10   = 1024
1 * 2^11   = 2048
------------------
totale     = 4000
Per la parte decimale invece le potenze sono negative
0 * 2^(-1) = 0
1 * 2^(-2) = 0.25
Quindi sommando il tutto avrei
  4000,25
Questo solo perchè però 4000,25 è un numero decimale che in binario può
essere rappresentato esattamente, ma la stragrande maggioranza
dei numeri decimali (so che è sbagliata una frase del genere)
non è rappresentabile esattamente con un numero finito di cifre binarie
lasciamo perdere la parte intera di  4,56 che è ovviamente
 100,.....
infatti 4=1*2^2+0*2^1+0*2^0 e concentriamoci sulla parte decimale.
Per ottenere la parte decimale si fa così
 prendo 0,56 lo moltiplico per 2
   0,56*
   2   =
   -----
   1,12   prendo 1 e lo sottraggo
   0,12*
   2   =
   -----
   0,24   prendo 0
   0,24*
   2   =
   -----
   0,48   prendo 0
   0,48*
   2   =
   -----
   0,96   prendo 0
   0,96*
   2   =
   -----
   1,92   prendo 1 e lo sottraggo
   0,92*
   2   =
   -----
   1,84   prendo 1 e lo sottraggo
   0,84*
   2   =
   -----
   1,68   prendo 1 e lo sottraggo
Non è come per 0,25 rappresentabile con un numero finito di cifre decimali
vediamo fino ad ora come è andata
ho preso:
1000111
che con il giochetto delle potenze negative del due è:
2^(-1) + 2^(-5) + 2^(-6) + 2^(-7) + 2^(-8) =
0,5+0,03125+0,015625+0,0078125+0,00390625=0,55859375
Non abbiamo 0,56
Supponiamo che
,1000111  venga approssimato con
,1001  =0,5625 (non è molto difficile approssimare così basta incrementare
di 2^(-8)=0,0039..
Avremo che Access moltiplica i due numeri:
4,5625*4000,25=18251,140625
Proprio quello che ottieni tu
Nono volevo essere pesante, volevo solo essere preciso e chiaro e farti
capire.
Singola precisione vuol dire che vengono utilizzati 32 Bit non vuol dire che
vengono usate meno cifre decimali, in doppia precisione i bit sono 64
quindi puoi capire che è notevolmente superiore la precisione con cui, un
numero
decimale non rappresentabile esattamente come binario, viene rappresentata.
Se vuoi ulteriori chiarimenti contattami.
Spero di esser stato chiaro
 Ciao   Danilo

     numero = 16
[snip]
ehm, qui sopra avrei dovuto scrivere
     numero = 123.456
chiedo venia
ciao

 Anche con il metodo che suggerisci tu si becca
l'arrotondamento.
Veramente io ieri ne avevo proposto (non suggerito) un altro,
basato sempre sulla manipolazione di stringhe, che pero`, a
differenza di questo tuo, non va in errore se VALORE e` un
intero;-)
Lo ripropongo in versione "internazionale":
    Dim Valore   As Double
    Dim Decimale As Double
    'Valore = ...
    Decimale _
      = Val( _
          "0." _
        & Mid$( _
          Str$(Valore) _
        , InStr(Str$(Valore) & ".", ".") + 1))
Ma... anche questo metodo funziona fino ad un certo numero di
decimali... altri ne chiariscono bene i motivi in questo
stesso thread.


 Lo ripropongo in versione "internazionale":
[...]
Si, l'aggiunta di quel puntino risolve senza altri controlli.
Comunque, devo avere l'algoritmo per calcolare i decimali
del pigreco. Per penitenza darò un'occhiata se si può estrapolare
qualche cosa di utile.
Di post sull'argomento ce ne saranno altri.

 ha scritto nel messaggio
news:Q_8w5.5566$XZ4....@news.infostrada.it...

 suggerito da Massimo.
scusate -  suggerito da Maurizio Borrelli
