Pagina 2 di 2 primaprima 1 2
Visualizzazione dei risultati da 11 a 18 su 18
  1. #11
    Utente di HTML.it L'avatar di sebamix
    Registrato dal
    Aug 2000
    Messaggi
    1,028

    Re: E' una sorta di bug...

    Originariamente inviato da Gammino
    In parole povere per VB6 aggiungendo 30 minuti alle 8.45 non si ottengono esattamente le 9.15.

    Credo che ciò sia dovuto al fatto che si sommano due numeri double periodici (8.45 e 0.30), anche se non ho ancora capito bene il motivo reale.

    Se provate questo codice capite bene l'enigna.
    Somma 30 minuti alle 8.45, confronta il valore ottenuto dalla somma con CDate("09:15") e ritorna False invece di True!

    codice:
    MsgBox "Se non erro 8:45 + 30 min = 9:15?  Proviamo..."
    MsgBox "Se a voi, in VB6, da True brucio il mio PC..."
    MsgBox (DateAdd("n", 30, CDate("8:45")) = CDate("9:15"))
    MsgBox "E, ancor più assurdo, i due valori Double sono identici!...: " & CDbl(DateAdd("n", 30, CDate("8:45"))) & " = " & CDbl(CDate("9:15"))
    MsgBox "Fatemi sapere!"
    Il tuo PC non deve essere immolato...
    ora comincio ad indagare e poi ti faccio sapere cosa ne ricavo.


  2. #12
    Utente di HTML.it L'avatar di sebamix
    Registrato dal
    Aug 2000
    Messaggi
    1,028
    MSDN dice:
    Quando altritipi di dati numerici vengono convertiti in Date, i valori a sinistra della virgola decimale rappresentano le informazioni relative alla data, mentre i valori a destra della virgola rappresentano l'orario. Mezzanotte corrisponde a 0 e mezzogiorno a 0,5. I numeri interi negativi rappresentano le date antecedenti al 30 dicembre 1899.

    Allora io ho fatto questa prova:
    codice:
    Dim test1 As Date
    Dim test2 As Date
    test1 = CDate("08.45.00")
    test2 = CDate("09.15.00")
    test1 = DateAdd("n", 30, test1)
    MsgBox test1 & " = " & test2 & " ? " & (test1 = test2)
    Naturalmente il risultato è erratico.

    codice:
    Dim test1 As Date
    Dim test2 As Date
    test1 = CDate("09.00.00")
    test2 = CDate("09.30.00")
    test1 = DateAdd("n", 30, test1)
    MsgBox test1 & " = " & test2 & " ? " & (test1 = test2)
    Qui fa giusto.

    perchè?

    MSDN ci dice che la parte intera della data convertita rappresenta la data vera e propria mentre i decimali rappresentano l'orario.
    quindi (in teoria) se tu fai date + 1 aggiungi un giorno e date + 0.5 aggiungi 12 ore.
    Si vede che l'ora 9.15.00 convertita rappresenta un numero (double?) periodico, VB si intorta e non riesce a fare il confronto nella maniera corretta. 9.30 rappresenta un numero non periodico...
    C'è di più. Se tu non fai la dateadd
    codice:
    Dim test1 As Date
    Dim test2 As Date
    test1 = CDate("09.15.00")
    test2 = CDate("09.15.00")
    MsgBox test1 & " = " & test2 & " ? " & (test1 = test2)
    funziona!

    Quindi la colpa potrebbe essere della dateadd che pone qualche bit in maniera sbagliata (IMHO of course).

    Questo è interessante:
    The Date Data Type
    Date and time values can be contained both in the specific Date data type and in Variant variables. The same general characteristics apply to dates in both types.
    For More Information___See the section, "Date/Time Values Stored in Variants," in "Advanced Variant Topics."
    When other numeric data types are converted to Date, values to the left of the decimal represent date information, while values to the right of the decimal represent time. Midnight is 0, and midday is 0.5. Negative whole numbers represent dates before December 30, 1899.
    ...

    Comunque, perchè non usi la funzione DateDiff?
    codice:
    Dim test1 As Date
    Dim test2 As Date
    test1 = CDate("08.45.00")
    test2 = CDate("09.15.00")
    test1 = DateAdd("n", 30, test1)
    MsgBox test1 & " = " & test2 & " ? " & (DateDiff("n", test1, test2) = 0)
    Funziona egregiamente...



    La settimana prossima diggo un po' di più in MSDN perchè a quest'ora, di sabato, sono abbastanza cotto

  3. #13
    Utente di HTML.it L'avatar di Gammino
    Registrato dal
    Nov 2001
    Messaggi
    195
    Sono al corrente del modo in cui VB conserva le variabili Date, cioè in pratica in unità di giorni e sue frazioni.
    Ho anche verificato che il problema non sono le variabili, ma le operazioni con le variabili.

    Credo anche tu abbia centrato il problema:
    Originariamente inviato da sebamix
    Si vede che l'ora 9.15.00 convertita rappresenta un numero (double?) periodico, VB si intorta e non riesce a fare il confronto nella maniera corretta. 9.30 rappresenta un numero non periodico...
    Invece per quanto riguarda DateDiff il codice che hai scritto:
    codice:
    MsgBox test1 & " = " & test2 & " ? " & (DateDiff("n", test1, test2) = 0)
    non verifica realmente il bug.

    Mi spiego: il problema sembra essere che sommando 8.45 e 30 min, essendo uno od entrambi numeri periodici, il risultato ha un arrotondamento che si porta dietro. Quindi, per esempio, il risultato vero non è 9.15, bensì 9.15.0000000000000000001 (tanto per capirci ).

    Il codice scritto da te non verifica questo bug proprio perchè a VB "sfugge" quella minima frazione di arrotondamento e se tu gli fai fare, sempre seguendo l'esempio, 9.15.0000000000000000001 - 9.15 luì ti ritorna 0, proprio perchè non riesce a gestire quella piccolissima frazione.

    In pratica nel codice tu hai fatto scaturire il bug con DateAdd e poi l'hai annullato con DateDiff...

    La cosa più ... è che non c'è modo di verificare la presenza di quello 0000001 (o quel che l'è).
    In compenso se il valore ottenuto dalla somma lo "pulisci" convertendolo in testo e poi lo riconverti in Date tutto và alla grande, proprio perchè convertendolo in String non può conservare quello 000001 malefico!

    Dai retta a me... It's a Bug!

    Comunque grazie e complimenti per la corposa analisi!

    Ci sono giornate in cui mi sembra che il mondo giri al contrario... poi mi sveglio e mi accorgo che purtroppo gira sempre nella stessa direzione: quella sbagliata!
    (Gammino)

  4. #14
    Utente di HTML.it L'avatar di sebamix
    Registrato dal
    Aug 2000
    Messaggi
    1,028
    :metallica

    E' che ho letto
    codice:
    On Error GoTo Bar
    E mi sono ispirato.
    Comunque VB è pieno di questi "errorini", non credere...
    Soprattutto con la converione dei tipi...

  5. #15
    codice:
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, Source As Any, ByVal Length As Long)
    
    Private Type double_data
        dw1 As Long
        dw0 As Long
    End Type
    
    Private Function rawdouble(ByVal d As Double) As String
    Dim d1 As double_data
    
        CopyMemory d1, d, 8
        rawdouble = Right("00000000" & Hex(d1.dw0), 8) & Right("00000000" & Hex(d1.dw1), 8)
        
    End Function
    
    Private Sub Command1_Click()
    
    Dim Data1 As Date, Data2 As Date
    
        Data1 = CDate("8:45")
        Data2 = CDate("0:30")
        
        Data2 = Data2 + Data1
        MsgBox "8:45 + 0:30 = 9:15, giusto? Lui dice che è " & (Data2 = #9:15:00 AM#)
        
        MsgBox "Proviamo con DateAdd..."
        
        Data1 = CDate("8:45")
        Data2 = CDate("0:30")
        
        Data1 = DateAdd("n", 30, Data1)
        MsgBox "8:45 + 0:30 = 9:15, giusto? Lui dice che è " & (Data1 = CDate("9:15"))
        
        MsgBox "Infatti " & rawdouble(Data1) & "<>" & rawdouble(CDate("9:15")) 
    
       'per colpa del bit meno significativo della mantissa
        
    End Sub
    Nei numeri in virgola mobile la somma di due numeri non sempre e' corretta, anzi, molto spesso e' approssimata, per lo scopo di memorizzare una data ci puo anche stare perdere precisione sul bit meno sgnificativo della mantissa, mica vogliamo misurare i picosecondi, quindi per fare i confronti conviene normalizzarsi le date usando i vari formatdate eccetera.

    E NON SOLO IN VB, MA IN TUTTI I PROGRAMMI CHE USANO IL CALCOLO IN VIRGOLA MOBILE.

  6. #16
    Utente di HTML.it L'avatar di Gammino
    Registrato dal
    Nov 2001
    Messaggi
    195
    Originariamente inviato da Andrea Simonassi
    E NON SOLO IN VB, MA IN TUTTI I PROGRAMMI CHE USANO IL CALCOLO IN VIRGOLA MOBILE.
    Lo stesso identico confronto che in VB6 restituisce False in VB.NET restituisce True...

    Scusa, dal basso della mia ciucciaggine (cf. ciuccio, asino... :gren: ) non conosco CopyMemory e quindi non ho capito cosa fa la fx rawdouble... Saresti così paziente da darmi una piccola spiegazione in merito?

    Grazie

    Intanto provo a premere F1... :gren:
    Ci sono giornate in cui mi sembra che il mondo giri al contrario... poi mi sveglio e mi accorgo che purtroppo gira sempre nella stessa direzione: quella sbagliata!
    (Gammino)

  7. #17
    Evidentemente VB.NET fa attenzione maggiore nei confronti e nelle operazioni tra date.

    Se pero' fai una serie di calcoli in virgola mobile avrai comunque degli errori.

    prova

    codice:
    Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
            Dim a As Double
            a = 1.0
            a = a / 5.5555555555555554E+20
            a = a * 5.5555555555555554E+20
            Debug.WriteLine(a = 1.0)
    
        End Sub
    la funzione rawdouble che ho sritto fa vedere i bit che compongono i due valori double, che differiscono per l'appunto di 1 bit.

    Copymemory effettua la copia a basso livello di un blocco di memoria in un altro, nel mio caso copia gli 8 byte che compongono il tipo double in una struttura che contiene due long da 4 byte ciascuno.

  8. #18
    Utente di HTML.it L'avatar di Gammino
    Registrato dal
    Nov 2001
    Messaggi
    195
    GRAZIE INFINITE!!!!

    6 stato gentilissimo
    Ci sono giornate in cui mi sembra che il mondo giri al contrario... poi mi sveglio e mi accorgo che purtroppo gira sempre nella stessa direzione: quella sbagliata!
    (Gammino)

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.